千家信息网

Java中如何实现线程通信

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,今天就跟大家聊聊有关Java中如何实现线程通信,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、synchronized加wait/notif
千家信息网最后更新 2026年11月03日Java中如何实现线程通信

今天就跟大家聊聊有关Java中如何实现线程通信,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1、synchronized加wait/notify方式

/** * wait和notify的使用 * wait和notify必须应用在synchronized块或方法内 * 下面的代码向跳交谊舞一样互相控制着对方的输出 */public class MutiThread_WaitNotify {    public static void main(String[] args) {        final Object lock = new Object();        Thread a = new Thread(new Runnable(){            @Override            public void run(){                synchronized (lock){                    try{                        lock.wait();                        System.out.println("A-1");                        lock.notify();                        lock.wait();                        System.out.println("A-2");                        lock.notify();                        lock.wait();                        System.out.println("A-3");                        lock.notify();                    }catch(InterruptedException e){                        e.printStackTrace();                    }                }            }        });        Thread b = new Thread(new Runnable(){            @Override            public void run(){                synchronized (lock){                    try{                        System.out.println("B-1");                        lock.notify();                        lock.wait();                        System.out.println("B-2");                        lock.notify();                        lock.wait();                        System.out.println("B-3");                        lock.notify();                        lock.wait();                        System.out.println("B-4");                    }catch(InterruptedException e){                        e.printStackTrace();;                    }                }            }        });        a.start();        b.start();    }}

2、ReentrantLock加Condition方式

/** * ReentrantLock和Condition的使用 * 在使用Conditioin的await和signal时,必须将这两个方法写在ReentrantLock的lock方法之后 */public class MutiThread_ReentrantLock_Condition {    public static void main(String[] args) {        ReentrantLock lock = new ReentrantLock();        Condition condition = lock.newCondition();        int i=1;        for(; i<=6; i++){            final int k = i;            Thread t1 = new Thread(new Runnable() {                @Override                public void run() {                    try{                        lock.lock();                        System.out.println("ThreadNo:A" + k + " is locked");                        // 通过condition.await将线程阻塞                        condition.await();                    }catch(InterruptedException e){                        e.printStackTrace();                    }finally{                        lock.unlock();                        System.out.println("ThreadNo:A"+k + " is unlocked");                    }                }            });            Thread t2 = new Thread(new Runnable() {                @Override                public void run() {                    if(k == 6){                        try{                            lock.lock();                            System.out.println("All Threads is signaled");                            // 通过condition.signalAll唤醒所有线程                            condition.signalAll();                        }catch(Exception e){                            e.printStackTrace();                        }finally{                            lock.unlock();                        }                    }else{                        System.out.println("threads can't signaled, wait a moment.");                    }                }            });            t1.start();            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            t2.start();        }    }}

3、闭锁方式

import java.util.concurrent.CountDownLatch;/** * 闭锁的使用 * 闭锁用于等待事件,当闭锁到达结束状态(本例中是闭锁的计数器值减为0)之前,所有线程都等待,当闭锁到达结束状态时,所有线程都通过 * 闭锁是一次性的,当闭锁到达结束状态后,将不会被重置,这个锁会永远打开并允许所有线程通过。 * 可以将代码中的NUM变量值变为2和4,分别试试什么效果 */public class MutiThread_CountDownLatch {    public static void main(String[] args) {        // 定义闭锁,并设置闭锁的计数器值为3        CountDownLatch lock = new CountDownLatch(3);        // 循环定义3个线程        int NUM = 3;        for(int i=1; i<=NUM; i++){            final int k = i;            Thread a = new Thread(new Runnable(){                @Override                public void run(){                    try{                        Thread.sleep(k * 1000);                        System.out.println("ThreadNo:A"+k);                        // 每个线程在休眠指定时间后将闭锁的计数器值减1,当闭锁的计数器值减到0时,闭所将被打开,从而使第二个循环中的所有线程才能通过                        lock.countDown();                        // 打印闭锁计数器的值                        System.out.println("ThreadNo:A"+k+"; getCount:"+lock.getCount());                    }catch(InterruptedException e){                        e.printStackTrace();                    }                }            });            a.start();        }        // 循环定义2个线程        for(int i=1; i<=2; i++){            final int k = i;            Thread b = new Thread(new Runnable(){                @Override                public void run(){                    try{                        System.out.println("ThreadNo:B"+k+" is waiting...");                        // 当闭锁的计数器值不为0时,线程将在此处被中断                        lock.await();                        // 当闭锁的计数器值等于0时,闭锁将被打开,所有等待的线程都将被唤醒                        System.out.println("ThreadNo:B"+k+" is notify");                    }catch(InterruptedException e){                        e.printStackTrace();                    }                }            });            b.start();        }    }}

4、栅栏的方式

import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/** * 栅栏的使用 * 栅栏用于等待线程,所有线程必须同时到达栅栏,才能继续执行 * 栅栏不是一次性的,可以被重置。 * 可以将代码中的NUM变量值变为5和7,分别试试什么效果 */public class MutiThread_CyclicBarrier {    public static void main(String[] args) {        // 定义栅栏,并设置栅栏需要等待的线程数为6        CyclicBarrier barrier = new CyclicBarrier(6);        int NUM = 100;        for(int i=1; i<=NUM; i++){            final int k = i;            Thread t = new Thread(new Runnable() {                @Override                public void run() {                    try{                        Thread.sleep(k * 1000);                        System.out.println("ThreadNo:"+k+" is waiting, getNumberWaiting:" + barrier.getNumberWaiting());                        // 栅栏设置的等待线程数为6,当线程数不够6个时,所有线程将在此等待                        barrier.await();                        // 当线程数达到6个时,栅栏将被打开,所有线程都将被唤醒                        System.out.println("ThreadNo:"+k+" is notify");                        // 栅栏被重置,以便下次继续使用                        barrier.reset();                    }catch(InterruptedException e){                        e.printStackTrace();                    } catch (BrokenBarrierException e) {                        e.printStackTrace();                    }                }            });            t.start();        }    }}

5、信号量的方式

import java.util.ArrayList;import java.util.List;import java.util.concurrent.Semaphore;/** * 信号量的使用 * 信号量用于控制同时访问某个资源的线程数量,信号量还可以用于实现某个资源池。 * 信号量管理者一组虚拟的许可,线程在执行操作时首先要获得许可,如果信号量的许可数量为0,那么accquire将阻塞直到有许可为止 * 信号量不是一次性的,当信号链的许可用完之后,可以通过release释放许可 */public class MutiThread_Semaphore {    public static void main(String[] args) {        // 定义信号量,并设置信号量的允许发放的最大许可数量为6        final Semaphore semaphore = new Semaphore(6);        // 定义集合,当信号量未发放的许可数量大于0则允许线程向集合内添加元素        final List set = new ArrayList<>();        int i = 1;        while(true){            final int k = i++;            Thread t = new Thread(new Runnable() {                @Override                public void run() {                    boolean res = false;                    try{                        System.out.println("ThreadNo:A"+k+", availablePermits:"+semaphore.availablePermits());                        // 当信号量允许发放的许可数量大于0,则会向集合内添加元素,否则将被中断于此                        semaphore.acquire();                        res = set.add("1");                        System.out.println("ThreadNo:A"+k+" add item success");                    }catch(InterruptedException e){                        e.printStackTrace();                    }finally{                        if(!res){                            semaphore.release();                        }                    }                }            });            Thread t2 = new Thread(new Runnable() {                @Override                public void run() {                    if(semaphore.availablePermits() == 0){                        // 如果信号量允许发放的许可数量等于0,则释放制定数量的许可                        semaphore.release(3); //释放3个许可                        System.out.println("ThreadNo:B"+k+" releasePermitNum:"+semaphore.availablePermits());                    }                }            });            t.start();            t2.start();            System.out.println("the num of set:"+set.size());            try {                Thread.sleep(2000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

A、join的使用

/** * join的使用 * 实现当调用join的线程执行完毕后,其他线程才能执行 */public class MutiThread_Join {    public static void main(String[] args) {        Thread a = new Thread(new Runnable(){            @Override            public void run(){                printNumber("A");            }        });        Thread b = new Thread(new Runnable(){            @Override            public void run(){                printNumber("B");            }        });        try{            a.start();            // a线程执行完毕后,b线程才能执行            a.join();            b.start();        }catch(InterruptedException e){            e.printStackTrace();;        }    }    public static void printNumber(String s){        System.out.println(s+" print:"+s);    }}

B、yield的使用

/** * yield,当一个线程中调用了这个方法后,这个线程就会把自己的CPU执行时间让给自己或其它线程, * 注意是让给自己或其它线程,并不是单纯让给其他线程。yield执行后,能让当前线程由运行状态 * 进入到就绪状态,将自己的CPU时间片让出来,让出来之后有可能是其它线程执行,也有可能是该线程 * 继续执行。优先级高的线程并不一定是首先执行,而是首先执行的概率会高一些。优先级在大量线程 * 执行的时候才能体现的出来。 */public class MutiThread_yield {    public static void main(String[] args) {        Thread t1 = new Thread(new Runnable() {            @Override            public void run() {                for(int i=0;i<10;i++){                    System.out.println("ThreadNo:A"+i);                    Thread.yield();                }            }        });        Thread t2 = new Thread(new Runnable() {            @Override            public void run() {                for(int i=0;i<10;i++){                    System.out.println("ThreadNo:B"+i);                    Thread.yield();                }            }        });        t1.setPriority(Thread.MIN_PRIORITY);        t2.setPriority(Thread.MAX_PRIORITY);        t1.start();        t2.start();    }}

看完上述内容,你们对Java中如何实现线程通信有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

0