20180126:通过Callable实现多线程、生产者-消费者问题、多线程下载(复制)文件
2018-01-27 22:16
525 查看
一、通过Callable实现多线程
1.Callable接口介绍
java.util.concurrent.Callable是一个泛型类接口,其中只有一个call()方法,call()方法会抛出Exception异常,且返回一个指定的泛型类对象:public
V call();
![](https://oscdn.geek-share.com/Uploads/Images/Content/201801/f70f754be42f90601ff59c8d9382daf4)
2.使用Callable接口实现多线程的步骤
1. 创建Callable接口子类实例化对象.
2. 创建FutureTask对象,FutureTask也是一个泛型类,且泛型要和Callable的泛型类型相同,
并将Callable对象传入FutureTask的构造方法中(FutureTask是Runnable接口的实现类)
3. 实例化Thread对象,并在构造方法中传入FutureTask对象
4. 启动线程.
用Callable接口实现多线程的使用场景是:一个线程需要另一个线程返回一个值时用到这种方法启动线程
写一个用Callable接口实现多线程的Demo:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201801/2aab549f9de75b193bb4d5cf190a0381)
从上述方法中可以看出:用Callable接口实现的线程类启动仍然靠的是线程类的start()方法,但若想获得线程的返回值,就
FutureTask的对象调用get()方法获得线程的返回对象。
二、生产者-消费者问题
生产者-消费者问题是多线程的一个经典问题,它描述的是生产者线程和消费者线程公用一块缓冲区,生产者是向缓冲区中添加东西,
消费者线程可以从缓冲区取走产品;
解决生产者/消费者问题的方法可以分为两类:
1. 采用某种机制保护生产者和消费者之间的同步;
2. 在生产者和消费者之间建立一个管道。
第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。
在java中有四种方法支持同步,其中前三个方法是同步方法,一个管道方法,但管道方法不经常用,所以这里就先不讨论:
wait()/notify()、notifyAll()方法;(只讨论这个。。。)
await()/signal()方法;
BlockintQueue阻塞队列方法;
[b]关于wait()/notify()方法[/b]
wait()/notify()、notifyAll()方法是父类Object的两个方法:
wait(): 当缓冲区已满/空时,生产者/消费者线程停止自己的执行,放弃锁,是自己处于等待状态,让其他线程执行。
notify(): 当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程可发出可执行的通知,同时放弃锁,使自己处于等待状态。
这就是生产者-消费者线程的基本模式,其实和日常生活中的买卖是一样的,生产者生产产品,由于市场作用生产的产品有上限,消费者不断购买产品,产品没了之后不能购买,但可以提醒生产者继续生产产品去让卖卖继续进行下去。
接下来写一个同步方法的生产者-消费者Demo:
测试结果如下啊:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201801/9d9e83c0772234292085741ea41e59c7)
三、多线程下载(复制)文件
1.Callable接口介绍
java.util.concurrent.Callable是一个泛型类接口,其中只有一个call()方法,call()方法会抛出Exception异常,且返回一个指定的泛型类对象:public
V call();
2.使用Callable接口实现多线程的步骤
1. 创建Callable接口子类实例化对象.
2. 创建FutureTask对象,FutureTask也是一个泛型类,且泛型要和Callable的泛型类型相同,
并将Callable对象传入FutureTask的构造方法中(FutureTask是Runnable接口的实现类)
3. 实例化Thread对象,并在构造方法中传入FutureTask对象
4. 启动线程.
用Callable接口实现多线程的使用场景是:一个线程需要另一个线程返回一个值时用到这种方法启动线程
写一个用Callable接口实现多线程的Demo:
package callable; import java.util.concurrent.Callable; public class CallableDemo implements Callable<String>{ //实现Callable泛型类,重写call方法 public String call() throws Exception { String str = Thread.currentThread().getName(); System.out.println(str+"开始偷袭长安。。。。"); System.out.println(str+"军路上遇到小股敌军势力。。。"); return "偷袭成功,不辱使命!"; } }
package callable; import java.util.concurrent.FutureTask; public class RunCallable { public static void main(String[] args) { //创建Callable的子类实例化对象 CallableDemo cd = new CallableDemo(); //将Callable的子类实例化对象传递 FutureTask<String> ft = new FutureTask<>(cd); try { Thread.currentThread().setName("诸葛亮线程"); System.out.println(Thread.currentThread().getName()+"开始进军。。。"); Thread.sleep(2000); //将ft对象作为参数传递到Thread对象中 Thread td = new Thread(ft, "魏延线程"); td.start(); //获取子线程的返回值 System.out.println("报告丞相:"+ft.get()); System.out.println(Thread.currentThread().getName()+"说:666"); } catch (Exception e) { e.printStackTrace(); } } }测试结果为:
从上述方法中可以看出:用Callable接口实现的线程类启动仍然靠的是线程类的start()方法,但若想获得线程的返回值,就
FutureTask的对象调用get()方法获得线程的返回对象。
二、生产者-消费者问题
生产者-消费者问题是多线程的一个经典问题,它描述的是生产者线程和消费者线程公用一块缓冲区,生产者是向缓冲区中添加东西,
消费者线程可以从缓冲区取走产品;
解决生产者/消费者问题的方法可以分为两类:
1. 采用某种机制保护生产者和消费者之间的同步;
2. 在生产者和消费者之间建立一个管道。
第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。
在java中有四种方法支持同步,其中前三个方法是同步方法,一个管道方法,但管道方法不经常用,所以这里就先不讨论:
wait()/notify()、notifyAll()方法;(只讨论这个。。。)
await()/signal()方法;
BlockintQueue阻塞队列方法;
[b]关于wait()/notify()方法[/b]
wait()/notify()、notifyAll()方法是父类Object的两个方法:
wait(): 当缓冲区已满/空时,生产者/消费者线程停止自己的执行,放弃锁,是自己处于等待状态,让其他线程执行。
notify(): 当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程可发出可执行的通知,同时放弃锁,使自己处于等待状态。
这就是生产者-消费者线程的基本模式,其实和日常生活中的买卖是一样的,生产者生产产品,由于市场作用生产的产品有上限,消费者不断购买产品,产品没了之后不能购买,但可以提醒生产者继续生产产品去让卖卖继续进行下去。
接下来写一个同步方法的生产者-消费者Demo:
package con2pro; public class Producer { private int count; //设置当前产品数量,初值定为0把 private final int MAX=5; //写一个生产的方法 public synchronized void makeProduct(){ try { String threadName = Thread.currentThread().getName(); //获得当前线程的线程名 if(count > MAX){ System.out.println(threadName+"生产的产品达到上限了。。。"); notifyAll(); wait(); }else{ System.out.println(threadName+"开始生产产品了,"); count++; Thread.sleep(1000); System.out.println(threadName+"生产了一件产品,现在产品的数量为:"+count); notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } //写一个消费产品的方法 public synchronized void buyProduct(){ try { String threadName = Thread.currentThread().getName(); if(count <= 0){ System.out.println(threadName+"产品已售空,请等待生产者生产。。。"); notifyAll(); wait(); }else{ System.out.println(threadName+"开始购买产品了,"); count--; System.out.println(threadName+"已经购买了产品,当前产品数为:"+count); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }写一个生产线程和购买线程:
package con2pro; public class Product implements Runnable{ private Producer pro; public Product(Producer pro){ this.pro = pro; } public void run(){ while(true){ pro.makeProduct(); } } }
package con2pro; public class Consumer implements Runnable{ private Producer pro; public Consumer(Producer pro){ this.pro = pro; } public void run(){ while(true){ pro.buyProduct(); } } }写一个测试类:
package con2pro; public class Run { public static void main(String[] args) { Producer pro = new Producer(); new Thread(new Product(pro),"卫龙").start(); new Thread(new Consumer(pro),"薇恩").start(); new Thread(new Consumer(pro),"德莱厄斯").start(); } }
测试结果如下啊:
三、多线程下载(复制)文件
相关文章推荐
- java利用lock和unlock实现消费者与生产者问题(多线程)
- 关于多线程的经典问题——生产者消费者,不能实现循环工作。
- Java实现 简单的多线程“生产者-消费者”问题
- 多线程实现生产者消费者问题 详细注释 事件+临界区 信号量+临界区2种方法
- java多线程总结六:经典生产者消费者问题实现
- 多线程经典问题之生产者消费者问题的JAVA实现
- Java 多线程实现生产者消费者问题(wait/notify)
- 使用jdk1.5的多线程 lock condition 实现方式实现 生产者消费者问题
- 生产者和消费者关系通过多线程来实现
- 生产者与消费者问题(java多线程实现)
- linux下多线程互斥量实现生产者--消费者问题和哲学家就餐问题
- 关于网宿厦门研发中心笔试的一道PV操作题:利用java中的多线程实现生产者与消费者的同步问题
- 用JAVA实现多线程(生产者与消费者问题)
- Java多线程实现生产者消费者延伸问题
- 多线程经典案例——生产者/消费者问题的Java实现与详解
- 多线程(线程间通信-多生产者多消费者问题-JDK1.5解决办法-范例),停止线程,线程中方法的区别,匿名内部类实现多线程,线程总结
- java多线程,这样的生产者消费者实现会有什么问题呢?
- java多线程总结六:经典生产者消费者问题实现
- Linux下用条件变量实现多线程间生产者与消费者问题
- 通过生产者消费者问题比较信号量和信号【Java实现】