博客
关于我
线程(下)--线程通信&&消费者问题
阅读量:285 次
发布时间:2019-03-03

本文共 6216 字,大约阅读时间需要 20 分钟。

线程通信是多线程程序中实现线程间相互调度和信息传递的重要机制。在Java中,线程通信主要通过锁、条件、可重入锁等机制实现。以下将从多个角度探讨线程通信的实现方法及其应用案例。

1. 线程通信的基本机制

线程通信的核心机制包括等待和唤醒。wait()方法使得线程进入阻塞状态,直到被另一个线程调用notify()notifyAll()唤醒。notify()方法会唤醒等待队列中优先级最高的线程,而notifyAll()则会唤醒所有等待的线程。

2. 实现Runnable接口的线程通信

在Java中,Runnable接口是一种轻量级的线程执行方式。以下是一个实现Runnable接口的线程通信示例:

import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class PrintNum implements Runnable {    private static int num = 0;    private static Lock lock = new ReentrantLock();    private static Condition con = lock.newCondition();    @Override    public void run() {        while (true) {            lock.lock();            con.signal();            num++;            if (num <= 100) {                System.out.println(Thread.currentThread().getName() + ":" + num);            } else {                lock.unlock();                break;            }            con.await();            lock.unlock();        }    }}

3. 使用synchronize修饰同步代码块

Runnable接口的实现中,可以通过synchronize修饰方法或代码块来实现线程同步。以下是一个使用synchronize修饰同步代码块的示例:

public class PrintNum implements Runnable {    private static int num = 0;    @Override    public void run() {        while (true) {            synchronized (this) {                this.notify();                if (num <= 100) {                    System.out.println(Thread.currentThread().getName() + ":" + num);                    num++;                } else {                    break;                }                try {                    this.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }}

4. 继承Thread类的线程通信

如果直接继承Thread类,可以通过Object对象作为锁,实现线程通信。以下是一个继承Thread类的线程通信示例:

public class PrintNum extends Thread {    private static int num = 0;    private static Object obj = new Object();    @Override    public void run() {        while (true) {            synchronized (obj) {                obj.notify();                if (num <= 100) {                    System.out.println(Thread.currentThread().getName() + ":" + num);                    num++;                } else {                    break;                }                try {                    obj.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }}

5. 消费者-生产者问题

消费者-生产者问题是多线程编程中的经典问题,涉及多个线程之间的协调。以下是一个简单的柜台类实现:

public class Counter {    private int num = 0;    public synchronized void add() {        if (num == 0) {            num++;            System.out.println("生产一个");            this.notify();        } else {            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public synchronized void sub() {        if (num == 1) {            num--;            System.out.println("消费一个");            this.notify();        } else {            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

6. 生产者线程

生产者线程负责在柜台中添加物品,以下是一个生产者线程的实现:

public class Productor extends Thread {    private Counter c;    public Productor(Counter c) {        this.c = c;    }    @Override    public void run() {        while (true) {            try {                Thread.sleep(1000);                c.add();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

7. 消费者线程

消费者线程负责从柜台中取走物品,以下是一个消费者线程的实现:

public class Customer extends Thread {    private Counter c;    public Customer(Counter c) {        this.c = c;    }    @Override    public void run() {        while (true) {            try {                Thread.sleep(1000);                c.sub();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

8. 测试类

以下是一个使用上述组件的测试类:

public class Test {    public static void main(String[] args) {        Counter c = new Counter();        Productor p = new Productor(c);        Customer ct = new Customer(c);        p.start();        ct.start();    }}

9. JDK8 以后的线程创建方法

在JDK8中,FutureTaskExecutorService提供了更简便的线程创建方式。以下是一个使用FutureTask的示例:

import java.util.concurrent.Callable;public class SumNumThread implements Callable {    @Override    public Integer call() throws Exception {        int sum = 0;        for (int i = 1; i <= 100; i++) {            sum += i;        }        return sum;    }}public class Test {    public static void main(String[] args) {        SumNumThread sum = new SumNumThread();        FutureTask futureTask = new FutureTask(sum);        Thread t = new Thread(futureTask);        t.start();        try {            Integer val = futureTask.get();            System.out.println(val);        } catch (InterruptedException e) {            e.printStackTrace();        } catch (ExecutionException e) {            e.printStackTrace();        }    }}

10. 使用ExecutorService创建线程池

ExecutorService提供了线程池的创建方式,可以根据需要配置线程池的大小。以下是一个使用ExecutorService的示例:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class SumNumThread implements Callable {    @Override    public Integer call() throws Exception {        System.out.println(Thread.currentThread().getName());        int sum = 0;        for (int i = 1; i <= 100; i++) {            sum += i;        }        return sum;    }}public class Test {    public static void main(String[] args) {        ExecutorService executorService = Executors.newFixedThreadPool(5);        SumNumThread sumNumThread = new SumNumThread();        executorService.submit(sumNumThread);        executorService.submit(sumNumThread);        executorService.submit(sumNumThread);        executorService.submit(sumNumThread);        executorService.submit(sumNumThread);        Future f = executorService.submit(sumNumThread);        try {            System.out.println(f.get());        } catch (InterruptedException e) {            e.printStackTrace();        } catch (ExecutionException e) {            e.printStackTrace();        }        executorService.shutdown();    }}

通过以上方法,可以实现线程间的通信与协调,确保多线程程序的正确执行。

转载地址:http://noul.baihongyu.com/

你可能感兴趣的文章
pandas.read_csv()的详解-ChatGPT4o作答
查看>>
PANDAS.READ_EXCEL()输出‘;溢出错误:日期值超出范围‘;而不存在日期列
查看>>
pandas100个骚操作:再见 for 循环!速度提升315倍!
查看>>
Pandas:如何根据其他列值的条件对列进行求和?
查看>>
Pandas:对给定列求和 DataFrame 行
查看>>
Pandas、groupby 和特定月份的求和
查看>>
Pandas、Matplotlib、Pyecharts数据分析实践
查看>>
Pandas中文官档 ~ 基础用法1
查看>>
Pandas中文官档~基础用法2
查看>>
SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)
查看>>
Pandas中文官档~基础用法5
查看>>
Pandas中文官档~基础用法6
查看>>
Pandas中的GROUP BY AND SUM不丢失列
查看>>
Pandas中的GROUP BY AND SUM不丢失列
查看>>
Pandas之iloc、loc
查看>>
pandas交换两列
查看>>
pandas介绍-ChatGPT4o作答
查看>>
pandas删除指定列里面内容的行
查看>>
pandas去除Nan值
查看>>
vc++多线程编程
查看>>