synchronized+notifyAll+wait方式:利用 num++ 进行让AB线程间接访问
public class thread1_100 { public static int num=1; private static final Object lock=new Object(); private void print(int target){ if(num>10) { return ; } synchronized (lock){ while(num<=10){ System.out.print(Thread.currentThread().getName()+": "); System.out.print(num); num++; lock.notifyAll(); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } lock.notifyAll();//主线程 } } public static void main(String[] args) { thread1_100 thread1_100=new thread1_100(); new Thread(()->{thread1_100.print(num);},"A").start(); new Thread(()->{thread1_100.print(num);},"B").start(); } }
结果显示:
A:1B:2A:3B:4A:5B:6A:7B:8A:9B:10
synchronized+notifyAll+wait方式:利用奇数和偶数交替打印
public class thread2__1_100 { public static void main(String[] args) { thread2__1_100 thread2__1_100=new thread2__1_100(); new Thread(()->{thread2__1_100.printabc(0);},"A").start(); new Thread(()->{thread2__1_100.printabc(1);},"B").start(); } private static int num=0; private static final Object lock=new Object(); private void printabc(int targetname) { while (true) { synchronized (lock) { while (num % 2 != targetname) { if(num>=10){//主线程没有退出 break; } try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (num >=10) { break; } num++; System.out.print(Thread.currentThread().getName() + ":" + num); lock.notifyAll(); } } } }
A:1B:2A:3B:4A:5B:6A:7B:8A:9B:10
前面两种方法的wait()方法和notifyAll()方法位置需要多多思考
根据前面两个例子可以判断是可以推断出这个题目的思考
如果使用的是第一种方法在最后多加入一个c,我们多运行几次会发现有问题
public class thread1_100 { public static int num=1; private static final Object lock=new Object(); private void print(int target){ if(num>10) { return ; } synchronized (lock){ while(num<=10){ System.out.print(Thread.currentThread().getName()+":"); System.out.print(num); num++; lock.notifyAll(); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } lock.notifyAll();//主线程 } } public static void main(String[] args) { thread1_100 thread1_100=new thread1_100(); new Thread(()->{thread1_100.print(num);},"A").start(); new Thread(()->{thread1_100.print(num);},"B").start(); new Thread(()->{thread1_100.print(num);},"c").start(); } }
结果:
A:1B:2A:3B:4A:5B:6A:7c:8A:9B:10 A:1B:2A:3B:4A:5B:6A:7c:8B:9c:10
在lock.notifyAll()方法执行后,并不能保证是按照ABC这样的顺序进行排序的。所以会出现不同结果
根据上述的第二种方法 用%判断
public class thread2__1_100 { public static void main(String[] args) { thread2__1_100 thread2__1_100=new thread2__1_100(); new Thread(()->{thread2__1_100.printabc(0);},"A").start(); new Thread(()->{thread2__1_100.printabc(1);},"B").start(); new Thread(()->{thread2__1_100.printabc(2);},"C").start(); } private static int num=0; private static final Object lock=new Object(); private void printabc(int targetname) { while (true) { synchronized (lock) { while (num % 3 != targetname) { if(num>=10){//主线程没有退出 break; } try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (num >=10) { break; } num++; System.out.print(Thread.currentThread().getName() + ":" + num); lock.notifyAll(); } } } }
结果:
A:1B:2C:3A:4B:5C:6A:7B:8C:9A:10
会发现结果和预想一样,那么同理线程数量增加时也是按照这个规律.
使用Lock对应的使用方法
public class thread4_1_100 { private int num=0; private Lock lock=new ReentrantLock(); private void printabc(String name,int targetnum){ for (int i = 0; i <10;) { lock.lock();//加锁 if(num%3==targetnum){ num++; i++;//确定是我要找的我才让i++ System.out.print(name); } lock.unlock();//操作完解锁 } } public static void main(String[] args) { thread4_1_100 thread4_1_100=new thread4_1_100(); new Thread(()->{thread4_1_100.printabc("A",0);}).start(); new Thread(()->{thread4_1_100.printabc("B",1);}).start(); new Thread(()->{thread4_1_100.printabc("C",2);}).start(); } }
结果:
ABCABCABCABCABCABCABCABCABCABC
使用join()方法 :
join() :与sleep() 方法一样,是一个可中断的方法,在一个线程中调用另一个线程的join() 方法,会使得当前的线程挂起,知直到执行join() 方法的线程结束。(!!)例如在B线程中调用A线程的join() 方法,B线程进入阻塞状态,直到A线程结束或者到达指定的时间。
既然是两个线程操作,是会有前后线程操作的
public class thread3_1_100 { public static void main(String[] args) throws InterruptedException { for (int i = 0; i <10 ; i++) { Thread t1 = new Thread(new printabc(null), "A"); Thread t2 = new Thread(new printabc(t1), "B"); Thread t3 = new Thread(new printabc(t2), "C"); t1.start(); t2.start(); t3.start(); Thread.sleep(10);//必须的 } } } class printabc implements Runnable{ public printabc(Thread beforeThread) { this.beforeThread = beforeThread; } private Thread beforeThread; @Override public void run() { if(beforeThread!=null){//第一个线程是特例 try { beforeThread.join();//前一个线程调用join() System.out.print(Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } }else{ System.out.print(Thread.currentThread().getName()+""); } } }
结果:
ABCABCABCABCABCABCABCABCABCABC
使用lock+Condition精准唤醒
需要唤醒哪个呢 就是A唤醒B,B唤醒C,C唤醒A依次循环
下一个线程.signal();方法
//精准唤醒 public class thread5_1_100 { private int num; private static Lock lock=new ReentrantLock(); private static Condition c1=lock.newCondition(); private static Condition c2=lock.newCondition(); private static Condition c3=lock.newCondition(); private void printabc(String name, int targetnum, Condition curthread,Condition nextthread){ for(int i=0;i<10;){ lock.lock(); while(num%3!=targetnum){ try { curthread.await(); } catch (InterruptedException e) { e.printStackTrace(); } } num++; i++; System.out.print(name); nextthread.signal(); lock.unlock(); } } public static void main(String[] args) { thread5_1_100 thread5_1_100=new thread5_1_100(); new Thread(()->{thread5_1_100.printabc("A",0,c1,c2);}).start(); new Thread(()->{thread5_1_100.printabc("B",1,c2,c3);}).start(); new Thread(()->{thread5_1_100.printabc("C",2,c3,c1);}).start(); }
结果:
ABCABCABCABCABCABCABCABCABCABC
使用信号量
public class thread6_1_100 { public Semaphore c1 = new Semaphore(1); public Semaphore c2 = new Semaphore(0); public Semaphore c3 = new Semaphore(0); public static void main(String[] args) { new thread6_1_100().printABC(); } public void printABC() { ExecutorService exe = Executors.newCachedThreadPool(); Thread t1 = new Thread() { @Override public void run() { while (true) { try { c1.acquire(); System.out.print("A"); c2.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread t2 = new Thread() { @Override public void run() { while (true) { try { c2.acquire(); System.out.print("B"); c3.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread t3 = new Thread() { @Override public void run() { while (true) { try { c3.acquire(); System.out.print("C"); c1.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }; exe.execute(t1); exe.execute(t2); exe.execute(t3); } }
来自大四学生(小白)的第二篇博客