进程和线程以及线程池(二)

阅读: 评论:0

进程和线程以及线程池(二)

进程和线程以及线程池(二)

山不过来,我就过去

生产者-消费者模型 

         在前面我们讲了很多关于同步的问题,然而在现实中,需要线程之间的协作。比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权。因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去。因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态。然后等待消费者消费了商品,然后消费者通知生产者队列有空间了。同样地,当队列空时,消费者也必须等待,等待生产者通知它队列中有商品了。这种互相通信的过程就是线程间的协作。

总的来说,就是如下图的这样,不断循环。

以学生类为资源举例

首先,要对线程等待,唤醒有基本的思想
不同种类线程之间的通信(等待唤醒机制)

出现线程安全问题了:
1.是不是多线程环境
2.是不是由共享资源
3.是否有多条语句在操作共享资源
线程的等待唤醒 Object类

void wait ()
在其他线程调用此对象的 notify () 方法或 notifyAll () 方法前,导致当前线程等待。

void notify ()
唤醒在此对象监视器上等待的单个线程。
void notifyAll ()
唤醒在此对象监视器上等待的所有线程。
生产线程:如果没有资源资源我就生产,有了资源我就等待,通知消费线程来消费
消费线程:有了资源我就消费,没有资源我就等着,你通知生产线程生产

1)定义一个学生类,定义一个标记,代表有无资源。

public class Student {public String name;public int age;//定义一个标记boolean flag;//表示资源,false就没有,ture就有
}

2定义一个生产资源SetThread类

public class SetThread extends Thread {Student student;int i=0;public SetThread(Student student) {this.student=student;}@Overridepublic void run() {while (true){synchronized (student){if(student.flag){try {student.wait();} catch (InterruptedException e) {e.printStackTrace();}}if(i%2==0){student.name="老大";student.age=15;}else {student.name="老二";student.age=12;}student.flag=true;//通知ifyAll();//唤醒以后,还要再次争抢时间片i++;}}}
}

3)定义一个消费GetThread类

public class GetThread extends Thread {//获得资源Student student;public GetThread(Student student) {this.student=student;}@Overridepublic void run() {while (true){synchronized (student){if(!student.flag){//没有资源try {student.wait();//等着:wait()方法 线程一旦等待 就要立马释放锁,等会被唤醒了,也就从这里醒来} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(student.name + "===" + student.age);//修改标记student.flag = ify();//通知}}}
}

4)接下来,开启线程

public class Test {public static void main(String[] args) {Student student = new Student();SetThread th1 = new SetThread(student);GetThread th2 = new GetThread(student);th1.start();th2.start();}
}

结果:

总的就是,生产-消费的关系一直循环(等待唤醒机制)

 

 线程池的概述与使用

1)线程池概述

程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。
而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池

2)内置线程池的概述

JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
            

public static ExecutorService newCachedThreadPool():                根据任务的数量来创建线程对应的线程个数    
public static ExecutorService newFixedThreadPool(int nThreads):    固定初始化几个线程
public static ExecutorService newSingleThreadExecutor():            初始化一个线程的线程池

         这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
            Future<?> submit(Runnable task)
            <T> Future<T> submit(Callable<T> task)
使用步骤:
            创建线程池对象
            创建Runnable实例
            提交Runnable实例
            关闭线程

3)匿名内部类的方式实现多线程

a.继承Tread类

b.继承Runnable类

public class Thread {public static void main(String[] args) {//匿名实现多线程//继承thread类new Thread(){public void run(){for(int x=0;x<111;x++){System.out.println(getName()+":"+x);}}}.start();//实现runable    new Thread(new Runnable() {@Overridepublic void run() {for(int x=0;x<100;x++){System.out.println("wwww");}}}).start();}
}

4)Executors工厂类来产生线程池

首先,定义一个MyCallable类来继承Callable,需要重新其中的call()方法。

 

public class MyCallable implements Callable<Integer> {int len;public MyCallable(int i) {len=i;}@Overridepublic Integer call() throws Exception{//此方法需要返回值,int sum=0;for (int i = 0; i <= len; i++) {sum=sum+i;}return sum;}
}

接下来开启线程池。

public class Test {public static void main(String[] args) throws ExecutionException, InterruptedException {//Callable<Integer> 这个任务接口,执行完之后会有返回值 跟线程池配合使用// Runnable 这个任务接口 执行完之后没有返回值//获取一个有指定数量线程对象的线程池ExecutorService service = wFixedThreadPool(3);//定义线程个数//submit  提交要执行的值返回任务,并返回表示挂起的任务结果的 Future。Future<Integer> sb1 = service.submit(new MyCallable(10));//第一个线程Future<Integer> sb2 = service.submit(new MyCallable(100));//Future<Integer> sb3 = service.submit(new MyCallable(1000));System.out.());System.out.());System.out.());service.shutdown();//关闭线程池}
}

记得最后关闭线程池。

 

 

 

本文发布于:2024-02-04 15:40:25,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170710767656775.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:线程   进程
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23