线程间的通信以及通过多种方式实现线程交叉打印的例子

进程与线程的区别:

进程是是计算机系统资源的最小单位,进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。

线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如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();
    }
}

 

posted @ 2019-03-16 00:25  LeeJuly  阅读(246)  评论(0)    收藏  举报