| 
 
| JAVA线程-任务 一、创建任务
 有两种方法:
 (1)实现Callable接口,重写call方法。
 这里的没有将任务与具体线程进行绑定。而是通过ExecutorService.submit()方法将任务提交给某个线程或是传递给FutureTask。
 (2)实现Runnable接口并编写run()方法
 这里的没有将任务与具体线程进行绑定。可以通过将Runnable对象提交给Thread类构造器实现任务与具体线程绑定。
 public class Task implements Runnable{
 //数据
 ……..
 //方法
 ……..
 //run()
 public void run(){
 ……….
 }
 }
 
 Thread thrd = new Thread(new Task());
 thrd.start();
 (3)尽管java提供了一些实现了Runable接口的类,并且可在这些类的run()方法体内可描述任务,但是,这违反了任务与线程、任务管理分离地原则,而不提倡使用。
 1)Thread用于创建线程和线程的状态管理等
 2)Future及其子类FutureTask用于任务的管理
 3)TimerTask用于描述计时或周期的任务(这是例外)
 二、从任务中产生返回值
 1、使用Callable接口
 Runnable接口是执行工作的独立任务,它不返回任何值。
 可通过实现Callable接口并可以重写Callable接口的call()方法来实现。
 Callable接口是一种具有类型参数的范型,其类型参数表示从call()中返回的类型。
 并且使用ExecutorService.submit()方法调用实现Callable接口的类的对象。
 例如:
 public Task implements Callable<String> {
 String result;
 …….
 public String call(){
 return …+ result;
 }
 }
 
 //main()
 ExecutorService exec = Executors.new CachedThreadPool();
 String relt = exec.submit(new Task());      // submit()返回一个范型Future对象
 ……..
 exec.shutdown();
 2、使用Future及其子类
 三、执行任务
 1、使用Thread类对象创建的线程执行任务
 (1)实现Runnable接口
 (2)调用Thread对象的start()和run()方法
 2、使用执行器(Executor)(即线程池)创建的线程执行任务
 (1)创建一个线程的代价有点高,因为需要与操作系统交互。而将实现Runnable的对象和实现Callable的对象提交给线程池,线程池中的线程会调用run()方法执行任务,当run()返回后,线程也不会死亡,而是在线程池中等待下一个任务。
 (2)使用线程池可以减少并发线程的数量。
 (3)实例
 public Task implements Runnable{ ……..}
 
 //main()
 ExecutorService exec = Executors.new CachedThreadPool();  //创建线程池
 exec.execute(new Task());                              //提交任务
 exec.shutdown();                                     //关闭线程池
 
 四、任务间通信
 1、使用管道实现任务间(线程间)输入/输出。
 2、JAVA中对应的类为PipedWriter类(允许任务向管道写)和PipedReader类(允许不同任务从同一个管道中读取)。
 3、例如:
 /*发送任务*/
 class Sender implements Runnable{
 private Random rand = new Random(47);
 private PipedWriter out = new PipedWriter();    //写入管道
 public PipedWriter get PipedWriter(){return out;}// 获取写入管道对象
 
 public void run(){
 try{
 while(true)
 for(char c = ‘A’; c <= ‘z’; c++){
 out.write(c);
 TimeUnit.MILLISECONDS.sleep(rand.netInt(500));
 }
 }catch(IOException e){
 print(e + “Sender write exception”);
 }catch(InterruptedException e){
 print(e + “Sender write interrupted”);
 }
 }
 }
 
 /*接收任务*/
 class Receiver implements Runnable{
 private PipedReader in;    //读取管道
 public Receiver(Sender sender) throws IOException{
 //读取管道与指定任务的写入管道绑定
 in = new PipedReader(sender.getPipedWriter());
 }
 
 public void run(){
 try{
 while(true){
 printnb(“Read: ” + (char)in.read() + “, ”);
 }
 }catch(IOException e){
 print(e + “Receiver read exception”);
 }
 }
 }
 
 //main()
 Sender sender = new Sender();              //发送任务
 Receiver receiver = new Receiver(sender);     //接收任务
 ExecutorService exec = Executors.newCachedThreadPool();
 exec.execute(sender);
 exec.execute(receiver);
 TimeUnit.SECONDS.sleep(4);
 exec.shutdownNow();
 
 //out
 Read: A, Read: B, Read: C, Read: D, Read: F, Read: G, Read: H, Read: I,
 java.lang.InterruptedException: sleep interrupted Sender
 sleep interrupted
 java.io.InterruptedIOException Receiver read exception
 
 六、取消任务
 1、使用使用Future及其子类,这是友好的
 2、使终止执行任务的线程,不确定
 3、关闭线程池,这也是暴力的,不计后果的
 七、线程在哪里
 1、一旦创建了一个程序,就存在一个线程,即main()
 2、隐式创建的线程,即使用执行器(Excutor)创建
 3、显式创建的线程,即直接使用Thread类创建
 
 
 
 | 
 |