
线程(下)--线程通信&&消费者问题
发布日期:2021-05-06 03:20:45
浏览次数:10
分类:技术文章
本文共 7033 字,大约阅读时间需要 23 分钟。
线程通信
就是多个线程之间相互牵制,相互调度执行
wait();让线程等待,进入阻塞状态,不会自动唤醒
notify();唤醒等待的线程,如果有多个,那就唤醒优先级高的
notifyAll();唤醒所有等待的线程
案例:交替打印1-100的数
1.使用lock锁,实现Runnable的方法
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class PrintNum implements Runnable { static int num = 0; static Lock lock = new ReentrantLock(); static Condition con = lock.newCondition(); @Override public void run() { while (true) { try { lock.lock(); con.signal();//唤醒线程 num++; if (num <= 100) { System.out.println(Thread.currentThread().getName() + ":" + num); } else { lock.unlock(); break; } con.await();//线程等待,并释放锁 lock.unlock(); } catch (InterruptedException e) { e.printStackTrace(); lock.unlock(); } } }}
测试类
public class Test { public static void main(String[] args) { PrintNum p =new PrintNum(); Thread p1 = new Thread(p); Thread p2 = new Thread(p); p1.start(); p2.start(); }}
2.实现Runnable的方法,使用synchronize修饰同步代码块
public class PrintNum implements Runnable{ static int num=0; @Override public void run() { while (true){ synchronized (this){ //implements Runnable 情况下,this只有一个,this可以充当锁 this.notify();//唤醒等待线程 使用锁对象来调用notify(),wait(); if (num<=100){ System.out.println(Thread.currentThread().getName()+":"+num); num++; }else{ break; } try { this.wait();//线程等待,并释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } } }}
测试类
public class Test { public static void main(String[] args) { PrintNum p =new PrintNum(); Thread p1 = new Thread(p); Thread p2 = new Thread(p); p1.start(); p2.start(); }}
3.继承Thread类的方法,使用synchronize修饰同步代码块
public class PrintNum extends Thread { static int num = 0; static Object obj =new Object();//继承Thread方式,由于创建了多个对象,需要自己创建一个唯一的对象,充当锁 @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(); } } } }}
测试类
public class Test { public static void main(String[] args) { PrintNum p1 = new PrintNum(); PrintNum p2 = new PrintNum(); p1.start(); p2.start(); }}
消费者生产者问题
1.柜台类,存放物品的类
/*柜台中 存放共享数据*/public class Counter { int num = 0;//初始物品数量为0 /* 生产商品*/ public synchronized void add() { if (num == 0) { num++; System.out.println("生产一个"); this.notify();//唤醒消费者线程 this表示同一个柜台 } else { try { this.wait();//生产者等待 } catch (InterruptedException e) { e.printStackTrace(); } } } /*消费商品 */ public synchronized void sub() { if (num == 1) { num--; System.out.println("消费一个"); this.notify();//唤醒生产者线程 this表示同一个柜台 } else { try { this.wait();//消费者等待 } catch (InterruptedException e) { e.printStackTrace(); } } }}
2.生产者线程
public class Productor extends Thread { Counter c; public Productor(Counter c) { this.c = c; } @Override public void run() { while (true) { try { Thread.sleep(1000);//休眠指定的时间 c.add();//调用add方法 } catch (InterruptedException e) { e.printStackTrace(); } } }}
3.消费者线程
/*消费者线程*/public class Customer extends Thread { 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(); } } }}
4.测试类
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(); }}
jdk8以后的两种创建线程的方法
以1-100求和问题
1.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(); //接受任务 FutureTaskfutureTask = 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(); } }}
2.ExecutorService创建线程池
public class SumNumThread implements Callable{ /* 可以向外界返回一个结果 可以抛出一个异常 */ @Override public Integer call() throws Exception { int sum=0; System.out.println(Thread.currentThread().getName()); 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); Futuref = executorService.submit(sumNumThread); try { System.out.println(f.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } executorService.shutdown(); }}
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年03月18日 22时01分36秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
2021年高处安装、维护、拆除考试资料及高处安装、维护、拆除证考试
2019-03-03
2021年电工(初级)考试及电工(初级)证考试
2019-03-03
2021年R2移动式压力容器充装考试总结及R2移动式压力容器充装模拟考试
2019-03-03
2021年安全员-B证(山东省)找解析及安全员-B证(山东省)考试总结
2019-03-03
2021年安全员-B证(山东省)考试APP及安全员-B证(山东省)考试技巧
2019-03-03
2021年安全员-A证(山东省)考试题及安全员-A证(山东省)报名考试
2019-03-03
2021年G1工业锅炉司炉考试报名及G1工业锅炉司炉模拟考试题库
2019-03-03
2021年G1工业锅炉司炉考试报名及G1工业锅炉司炉模拟考试题库
2019-03-03
2021年安全员-B证(山东省)考试内容及安全员-B证(山东省)模拟考试题
2019-03-03
2021年高压电工考试题库及高压电工找解析
2019-03-03
从xx离职随笔
2019-03-03
大数据学习之Spark——00Spark项目的pom.xml文件
2019-03-03
大数据学习之Spark——01Spark概述
2019-03-03
大数据学习之Spark——03Spark代码初体验(Word Count)
2019-03-03
LeetCode0234. 回文链表
2019-03-03
比特币史话·78 | 有容乃大(2): 零食售卖机
2019-03-03
比特币史话·96 | 隐私(3): 熔币重铸
2019-03-03
Filecoin主网上线,它是谁、割了谁?
2019-03-03