第三章 线程基本概念(三)

    技术2024-11-07  16

    1. volatile关键字

    可以保证在多线程环境下声明了volatile的变量的可见性,即一个线程修改了改变的值,其他变量能够看到修改后的结果,但是它不能代替锁,即保证不了原子性。下面的代码计算i的值,每个线程计数10000,但是10个线程都执行完,却始终少于100000。

    public class PlusV { private static volatile int i=0; public static class PlusTask implements Runnable { @Override public void run() { for(int k=0; k<10000; k++) { i++; } } } public static void main(String[] args) throws InterruptedException { Thread[] threads = new Thread[10]; for(int i=0; i<10; i++) { threads[i] = new Thread(new PlusTask()); threads[i].start(); } // 让这10个线程都运行结束 for(int i=0; i<10; i++) { threads[i].join(); } System.out.println(i); } }

    2. 线程组

    将相同功能的线程放置在一个线程组中,可以轻松处理几十个上百个线程。好的习惯是在往线程组中添加线程的时候最好将线程的名称描述清楚。

    public class ThreadGroupName implements Runnable{ public static void main(String[] args) { ThreadGroup tg = new ThreadGroup("PrintGroup"); Thread t1 = new Thread(tg, new ThreadGroupName(), "T1"); Thread t2 = new Thread(tg, new ThreadGroupName(), "T2"); t1.start(); t2.start(); System.out.println(tg.activeCount());// 活动线程的总数 tg.list();// 打印这个线程组中所有线程的信息 } @Override public void run() { String groupAndName = Thread.currentThread().getThreadGroup().getName() + "-" + Thread.currentThread().getName(); while(true) { System.out.println("I am " + groupAndName); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } }

    3. 守护线程(Daemon)

    特点是当所有的用户线程都执行结束后,守护线程也会自动退出执行。

    public class DaemonDemo { public static class DaemonT extends Thread { @Override public void run() { while(true) { System.out.println("I am alive"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { Thread t = new DaemonT(); t.setDaemon(true);// 将线程设置成守护线程 t.start(); Thread.sleep(2000); } }

    4. 线程优先级

    Java优先级1-10,但是通常使用1,5,10。高优先级的线程更倾向于先执行结束。

    public class PriorityDemo { public static class HightPriority extends Thread { static int count = 0; public void run() { while (true) { synchronized (PriorityDemo.class) { count++; if (count > 10000000) { System.out.println("HightPriority is complete"); break; } } } } } public static class LowPriority extends Thread { static int count = 0; public void run() { while (true) { synchronized (PriorityDemo.class) { count++; if (count > 10000000) { System.out.println("LowPriority is complete"); break; } } } } } public static void main(String[] args) { Thread high = new HightPriority(); Thread low = new LowPriority(); high.setPriority(Thread.MAX_PRIORITY); low.setPriority(Thread.MIN_PRIORITY); low.start(); high.start(); } }

    5. synchronized实现线程间同步

    对需要线程同步执行的代码加锁,从而使得每次只能有一个线程进入同步代码块,进而保证线程的安全性。

    指定加锁对象:对给定对象加锁,进入同步代码块前获得对象的锁。

    public class AccountingSync implements Runnable { private static AccountingSync instance = new AccountingSync(); static volatile int i = 0; public void increase() { i++; } @Override public void run() { for (int j = 0; j < 10000000; j++) { synchronized (instance) { increase(); } } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(instance); Thread t2 = new Thread(instance); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); } }

    直接作用在实例方法上:相当于对当前实例加锁,进入同步代码块需要获得当前实例的锁。

    public class AccountingSync2 implements Runnable { private static AccountingSync2 instance = new AccountingSync2(); static volatile int i = 0; public synchronized void increase() { i++; } @Override public void run() { for (int j = 0; j < 10000000; j++) { increase(); } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(instance); Thread t2 = new Thread(instance); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); } }

    直接作用与静态方法:相当于对当前类加锁,进入同步代码块前要获得当前类的锁。

    public class AccountingSyncClass implements Runnable{ static int i = 0; public static synchronized void increase() { i++; } @Override public void run() { for (int j=0; j<10000000; j++) { increase(); } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new AccountingSyncClass()); Thread t2 = new Thread(new AccountingSyncClass()); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); } }

    下一章 多线程中隐蔽的错误:https://blog.csdn.net/qq_35165775/article/details/107118559

    Processed: 0.011, SQL: 9