首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

第二十一章-并发(一)

2012-09-27 
第二十一章-并发(1)一、Thread类????? Thread构造方法只需要一个Runnable对象。调用Thread对象的start()方法

第二十一章-并发(1)

一、Thread类

????? Thread构造方法只需要一个Runnable对象。调用Thread对象的start()方法将为该线程执行必要的初始化操作,然后自动调用Runnable对象的run()方法以便在这个新线程中启动该任务。直到该线程执行完run()方法并自动消亡之前,垃圾回收器无法清除它。

Thread thread = new Thread(new Runnable(){@Overridepublic void run(){//线程执行的代码}});thread.start();                  //启动线程

????? 每个线程都有自己的优先级(每个Thread类都有priority属性及其setter和getter),尽管CPU处理现有线程集的顺序是不确定的,但是调度器将倾向于让优先权最高的线程执行。然而,这并不是意味着优先权较低的线程将得不到执行。优先权较低的线程仅仅是执行的频率较低。在绝大多数时间里,所有线程都应该以默认的优先权运行(这时Thread的默认设置)。

?

二、使用Executor

????? Java SE5的java.util.concurrent包中的执行器(Executor)将为你管理Thread对象,从而简化了并发编程。Excecutor在客户端和任务执行之间提供了一个间接层;与客户端直接执行任务不同,这个中介对象将执行任务。Executor允许你管理异步任务的执行,而无需显示地管理线程的声明周期。Executor在Java SE5/6中是启动任务的优选方法。

/** * 自定义Runnable类 */public class MyTask implements Runnable{private int id = 0;public MyTask(int id){this.id = id;}@Overridepublic void run(){try{System.out.println("Start task - id : " + id);Thread.sleep(1000);System.out.println("Doing task - id : " + id);Thread.sleep(1000);System.out.println("Finish task - id : " + id);}catch (InterruptedException e){e.printStackTrace();}}}

?

?CachedThreadPool

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ExecutorTest{public static void main(String[] args){/* * newCachedThreadPool构造一个动态的线程池。当调用 execute 方法启动一个线程时,将重用线程池内的空闲线程。 * 如果线程池内无可用的空闲线程,则创建一个新线程并添加到池中。当线程池内某个线程超过60秒未被使用时, 该线程会被移除并销毁。 */ ExecutorService exeService = Executors.newCachedThreadPool(); exeService.execute(new MyTask(1)); exeService.execute(new MyTask(2)); exeService.shutdown(); //关闭线程池,拒绝新的任务提交        }}

输出:

Start task - id : 1Start task - id : 2Doing task - id : 2Doing task - id : 1Finish task - id : 2Finish task - id : 1

?FixedThreadPool:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ExecutorTest{public static void main(String[] args){/* * newFixedThreadPool构造一个固定大小的线程池,当池内的所有线程都在执行时,新的任务将被添加进等待队列。 * 池内的线程在显式关闭之前都不会被销毁。 */ ExecutorService exeService = Executors.newFixedThreadPool(2); exeService.execute(new MyTask(1)); exeService.execute(new MyTask(2)); exeService.execute(new MyTask(3));//当前两个线程中的某个执行完时才开始执行 exeService.shutdown();//关闭线程池,拒绝新的任务提交        }}

?输出

Start task - id : 1Start task - id : 2Doing task - id : 1Doing task - id : 2Finish task - id : 1Start task - id : 3Finish task - id : 2Doing task - id : 3Finish task - id : 3

?SingleThreadExecutor:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ExecutorTest{public static void main(String[] args){/* * newSingleThreadExecutor构造一个单线程的执行器(就像大小为1的FixedThreadPool),多个任务将会排队顺序执行。 */ExecutorService exeService = Executors.newSingleThreadExecutor();//任务都进入等待队列顺序执行exeService.execute(new MyTask(1));exeService.execute(new MyTask(2));exeService.execute(new MyTask(3));exeService.shutdown();//关闭线程池,拒绝新的任务提交        }}

?输出

Start task - id : 1Doing task - id : 1Finish task - id : 1Start task - id : 2Doing task - id : 2Finish task - id : 2Start task - id : 3Doing task - id : 3Finish task - id : 3

也可搭配使用ThreadFactory

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;public class ExecutorTest{/** * 自定义Runnable类 */static class MyTask implements Runnable{private int id = 0;public MyTask(int id){this.id = id;}@Overridepublic void run(){try{System.out.println("Start task - id : " + id);Thread.sleep(1000);System.out.println("Doing task - id : " + id);Thread.sleep(1000);System.out.println("Finish task - id : " + id);}catch (InterruptedException e){e.printStackTrace();}}}/** * 自定义ThreadFactory,能让你在创建每个线程之前做相同的处理 */static class MyThreadFactory implements ThreadFactory{@Overridepublic Thread newThread(Runnable r){System.out.println("start new thread with factory : " + r);Thread thread = new Thread(r);return thread;}}public static void main(String[] args){ExecutorService exeService = Executors.newCachedThreadPool(new MyThreadFactory());exeService.execute(new MyTask(1));exeService.execute(new MyTask(2));}}

?输出

start new thread with factory : java.util.concurrent.ThreadPoolExecutor$Worker@47b480start new thread with factory : java.util.concurrent.ThreadPoolExecutor$Worker@10d448Start task - id : 1Start task - id : 2Doing task - id : 1Doing task - id : 2Finish task - id : 2Finish task - id : 1
?

?

三、后台线程

????? 后台线程(daemon),是指在程序运行的时候在后台提供通用服务的线程,并且这种线程并不属于程序中不可或缺的部分。因此,当所有非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。(简单来说,后台线程就是为了提供其他线程所需服务而存在的线程,类似垃圾回收器为我们的程序进行垃圾回收服务,而被服务的线程一旦退出或消亡,这些服务线程也就没必要存在了,因此在我们的所有程序执行完之后垃圾回收器就会退出。)我们可以在任意Thread类上使用setDaemon方法来设置该线程为后台线程。

public class DaemonThreadTest{public static void main(String[] args){//该线程每隔一秒输出,没设置结束条件Thread daemonThread = new Thread(new Runnable(){public void run(){while (true){try{System.out.println("Daemon Running!");Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}});//setDaemon方法将该线程设置为后台线程。daemonThread.setDaemon(true);Thread myThread = new Thread(new Runnable(){public void run(){try{System.out.println("Start my thread!");Thread.sleep(1000);System.out.println("Doing my thread!");Thread.sleep(1000);System.out.println("Finish my thread!");Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}});/* * 启动两个线程,daemonThread在myThread线程结束后自动结束 */daemonThread.start();myThread.start();}}

?输出

Daemon Running!Start my thread!Daemon Running!Doing my thread!Daemon Running!Finish my thread!Daemon Running!

?

四、异常捕获

由于线程的本质特性,使得你不能捕获从线程中逃逸的异常。一旦异常逃出任务的run()方法,它就会传播到控制台。

/** * 该线程一旦执行会抛出一个异常。 */class ExceptionThread extends Thread{public ExceptionThread(String threadName){super(threadName);}@Overridepublic void run(){throw new RuntimeException(new Error("Error from ExceptionThread!"));}}/** *  异常处理器,负责在线程异常抛出时执行某些操作。 */class ThreadExceptionHandler implements Thread.UncaughtExceptionHandler{@Overridepublic void uncaughtException(Thread t, Throwable e){//打印出异常信息System.out.println("Exception caughted !");System.out.println("From : " + t);System.out.println("Message : " + e);}}public class ThreadExceptionTest{public static void main(String[] args){String threadName = "Thread with handler";Thread thread= new ExceptionThread(threadName);//设置异常处理器                thread.setUncaughtExceptionHandler(new ThreadExceptionHandler());thread.start();/* * 在Thread类中有一静态方法Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) * 能为所有的线程设置一个默认的异常处理器。*/}}

?输出

Exception caughted !From : Thread[Thread with handler,5,main]Message : java.lang.RuntimeException: java.lang.Error: Error from ExceptionThread!
?

?

热点排行