线程间的通信以及通过多种方式实现线程交叉打印的例子
进程与线程的区别:
进程是是计算机系统资源的最小单位,进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
同一进程内的线程共享本进程的资源如内存,I/O,cpu等,进程之间的资源是独立的。
java中每创建一个新的线程就会产生一个新的调用栈。
我们从一个题来进入:
3个数组交叉打印
1.通过synchronized,notify(),wait(),notifyAll()来实现
关于synchronized/lock区别:
notify(),wait(),notifyAll(),必须先获得对象级别的锁才能执行。
wait():当执行wait()的时候,当前线程会被放到“预执行队列”,当前线程释放锁。
notify():执行以后不会立刻释放锁,而是等 这个线程执行完以后,就是退出synchronized代码块以后才会释放锁。
在一个线程中我们总是通过while语句轮询来判断一个条件,这样会很浪费CPU资源
第一轮 线程A执行,线程A先获取c锁,再获取a锁,线程B获取b锁,等待c锁,线程C等待a锁
第二轮线程A释放a,释放c并等待c,线程B得到c执行,线程C获取a,等待b
第三轮线程B释放c,释放b等待b,线程C执行,线程A获取c,等待a
public class SysnABC { public static class ThreadPrinter implements Runnable { private String name; private Object prev; private Object self; private int[] array; private ThreadPrinter(String name, Object prev, Object self,int[] array) { this.name = name; this.prev = prev; this.self = self; this.array = array; } @Override public void run() { int size = array.length; int count = size; while (count > 0) { // 多线程并发,不能用if,必须使用whil循环 synchronized (prev) { // 先获取 prev 锁 synchronized (self) {// 再获取 self 锁 System.out.println(name+":"+array[size-count]); count--; self.notifyAll();// 唤醒其他线程竞争self锁,注意此时self锁并未立即释放。 } // 此时执行完self的同步块,这时self锁才释放。 try { if (count == 0) {// 如果count==0,表示这是最后一次打印操作,通过notifyAll操作释放对象锁。 prev.notifyAll(); } else { prev.wait(); // 立即释放 prev锁,当前线程休眠,等待唤醒 } } catch (InterruptedException e) { e.printStackTrace(); } } } } } public static void main(String[] args) throws InterruptedException { Object a = new Object(); Object b = new Object(); Object c = new Object(); int[] num1= {1,2,3,4,5}; int[] num2= {6,7,8,9,10}; int[] num3= {10,11,12,13,15}; ThreadPrinter pa = new ThreadPrinter("Thread-A", c, a,num1); ThreadPrinter pb = new ThreadPrinter("Thread-B", b, c,num2); ThreadPrinter pc = new ThreadPrinter("Thread-C", a, b,num3); new Thread(pa).start(); new Thread(pb).start(); new Thread(pc).start(); } }
2.使用Lock+Condition:
public class LockABC { private static Lock lock = new ReentrantLock(); private static Condition A = lock.newCondition(); private static Condition B = lock.newCondition(); private static Condition C = lock.newCondition(); private static int count = 0; static class ThreadA extends Thread { private int[] a= {1,2,3,4,5}; @Override public void run() { try { lock.lock(); for (int i = 0; i < a.length; i++) { while (count % 3 != 0) A.await(); // A释放lock锁 System.out.println("Thread-A:"+a[i]); count++; B.signal(); // A执行完唤醒B线程 } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } static class ThreadB extends Thread { private int[] b= {6,7,8,9}; @Override public void run() { try { lock.lock(); for (int i = 0; i < b.length; i++) { while (count % 3 != 1) B.await(); // B释放lock锁,当前面A线程执行后会通过B.signal()唤醒该线程 System.out.println("Thread-B:"+b[i]); count++; C.signal();// B执行完唤醒C线程 } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } static class ThreadC extends Thread { private int[] c= {10,11,12,13,15}; @Override public void run() { try { lock.lock(); for (int i = 0; i < c.length; i++) { while (count % 3 != 2) C.await();// C释放lock锁 System.out.println("Thread-C:"+c[i]); count++; A.signal();// C执行完唤醒A线程 } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public static void main(String[] args) throws InterruptedException { new ThreadA().start(); new ThreadB().start(); new ThreadC().start(); } }
3.用CyclicBarrier帮我们实现
关于CountDownLatch、CyclicBarrier和 Semaphore:
public class CyclicBarrierABC { private final CyclicBarrier barrier; private final List<Integer> list; public CyclicBarrierABC() { list = Collections.synchronizedList(new ArrayList<Integer>()); barrier = new CyclicBarrier(3,newBarrierAction()); } public Runnable newThreadOne() { int num1[]= {1,2,3,4,5}; return new Runnable() { public void run() { for (int i = 0; i < num1.length; i++) { list.add(num1[i]); try { barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }; } public Runnable newThreadTwo() { int num2[]= {6,7,8,9,10}; return new Runnable() { public void run() { for (int i = 0; i < num2.length; i++) { list.add(num2[i]); try { barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }; } public Runnable newThreadThree() { int num3[]= {10,11,12,13,15}; return new Runnable() { public void run() { for (int i = 0; i < num3.length; i++) { list.add(num3[i]); try { barrier.await(); Thread.sleep(100); } catch (InterruptedException | BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }; } private Runnable newBarrierAction(){ return new Runnable() { @Override public void run() { Collections.sort(list); list.forEach(c->System.out.println(c)); list.clear(); } }; } public static void main(String args[]){ CyclicBarrierABC Cycli = new CyclicBarrierABC(); Cycli.run(Cycli.newThreadOne()); Cycli.run(Cycli.newThreadTwo()); Cycli.run(Cycli.newThreadThree()); } private void run(Runnable runnable) { new Thread(runnable).start(); } }
对于一个数组,一个线程打印奇数,另外一个线程打印偶数
public class LockAB { private static Lock lock = new ReentrantLock(); private static Condition A = lock.newCondition(); private static Condition B = lock.newCondition(); private static int a[] = {1,2,3,4,5,6,7,8,9}; private static int count=0; static class ThreadA extends Thread { @Override public void run() { try { lock.lock(); for (int i = 0; i < a.length; i++) { if(a[count] % 2== 0) { A.await(); } else { System.out.println("Thread-A:"+a[count]); count++; } B.signal(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } static class ThreadB extends Thread { @Override public void run() { try { lock.lock(); for (int i = 0; i < a.length; i++) { if(a[count] % 2 != 0) { B.await(); } else { System.out.println("Thread-B:"+a[count]); count++; } A.signal(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public static void main(String[] args) throws InterruptedException { new ThreadA().start(); new ThreadB().start(); } }
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10540387.html

浙公网安备 33010602011771号