线程管理
来源:互联网 发布:大富翁4官方下载mac版 编辑:程序博客网 时间:2024/05/17 04:00
1.线程的创建和运行
- 继承Thread类,并且覆盖run()方法
- 创建一个实现Runnable接口的类。使用带参数的Thread构造器来创建Thread对象。这个参数就是实现Runnable接口的类的一个对象
2.线程信息的获取和设置
- ID:保存了线程的唯一标识符
- Name:保存了线程的名称
- Priority:保存了线程对象的优先级。线程的优先级是从1到10,其中1是最低优先级
- Status:保存了线程的状态。在Java中,线程的状态有6种:new、runnable、blocked、waiting、time waiting或者terminated
3.线程的中断
Thread类有一个表明线程被中断与否的属性,他存放的是布尔值。线程的interrupt()方法被调用时,这个属性就会被设置为true。isInterrupted()方法只是返回这个属性的值。
4.线程中断的控制
如果线程实现了复杂的算法并且分布在几个方法中,或者线程里有递归调用的方法,我们就得使用一个更好的机制来控制线程的中断。为了达到这个目的,Java提供了InterruptedException异常。当检查到线程中断的时候,就抛出这个异常,然后在run()中捕获并处理这个异常。
import java.io.File;public class FileSearch implements Runnable{private String initPath;private String fileName;public FileSearch(String initPath, String fileName) {this.initPath = initPath;this.fileName = fileName;}@Overridepublic void run() {File file = new File(initPath);if (file.isDirectory()) {try {directoryProcess(file);} catch (InterruptedException e) {System.out.printf("%s: The search has been interrupted",Thread.currentThread().getName());}}}private void directoryProcess(File file)throws InterruptedException {File[] files = file.listFiles();if (files!=null) {for (int i = 0; i < files.length; i++) {if (files[i].isDirectory()) {directoryProcess(files[i]);}else {fileProcess(files[i]);}}}if (Thread.interrupted()) {throw new InterruptedException();}}private void fileProcess(File file)throws InterruptedException {if (file.getName().equals(fileName)) {System.out.printf("%s : %s\n",Thread.currentThread().getName(),file.getAbsolutePath());}if (Thread.interrupted()) {throw new InterruptedException();}}}
不管递归调用了多少次,只要线程检测到它已经被中断了,就会立即抛出Interrupted异常,然后继续执行run()方法。
5.线程的休眠和恢复
import java.util.Date;import java.util.concurrent.TimeUnit;public class FileClock implements Runnable{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.printf("%s\n",new Date());try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {System.out.printf("The FileClock has been interrupted");}}}}
当调用sleep()方法之后,线程会释放CPU并且不再继续执行任务。在这段时间内,线程不占用CPU时钟,所以CPU可以执行其他的任务。
如果休眠中线程被中断,该方法就会立即抛出InterruptedException异常,而不需要等待到线程休眠时间结束。
- Java并发API还提供了另一个方法来使线程对象释放CPU,即yield()方法,它将通知JVM这个线程对象可以释放CPU了。JVM并不保证遵循这个要求。通常来说,yield()方法只做调试使用。
6.等待线程的终止
Thread thread1 = new Thread(new DataSourcesLoader());Thread thread2 = new Thread(new NetworkConnectionsLoader());thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.printf("Main : Configuration has been loaded:%s\n", new Date());
运行这个程序时,你会看到两个线程对象是如何运行的。当两个子线程运行结束的时候,主线程对象才会继续运行并打印出最终的信息。
7.守护线程的创建和运行
Java里有一种特殊的线程叫做守护线程。这种线程的优先级很低,通常来说,当同一个应用程序里没有其他的线程运行的时候,守护线程才运行。当守护线程是程序中唯一运行的线程时,守护线程执行结束后,JVM也就结束了这个程序。因为这种特性,守护线程通常被用来作为同一程序中普通线程的服务提供者。他们通常是无限循环的,以等待服务请求或者执行线程的任务。
setDaemon()方法只能在start()方法被调用之前设置。一旦线程开始运行,将不能再修改守护状态。
isDaemon()方法被用来检查一个线程是不是守护线程,返回值true表示这个线程是守护线程,false表示这个线程是用户线程。
8.线程中不可控异常的处理
- 非运行时异常(Checked Exception):这种异常必须在方法声明的throws语句指定,或者在方法体内捕获。
- 运行时异常(Unchecked Exception):这种异常不必再方法声明中指定,也不需要在方法体中捕获。
import java.lang.Thread.UncaughtExceptionHandler;public class ExceptionHandler implements UncaughtExceptionHandler{@Overridepublic void uncaughtException(Thread t, Throwable e) {System.out.println("An exception has been captured");System.out.println("Thread : "+t.getId());System.out.println("Exception: "+e.getClass().getName()+": "+e.getMessage());System.out.println("Stack Trace: ");e.printStackTrace(System.out);System.out.println("Thread status: "+t.getState());}}
public class Task implements Runnable{@Overridepublic void run() {int numero = Integer.parseInt("TTT");}}
public class Main {public static void main(String[] args) {Thread thread = new Thread(new Task());thread.setUncaughtExceptionHandler(new ExceptionHandler());;thread.start();}}当一个线程抛出了异常并且没有被捕获时(这种情况只可能是运行时异常),JVM检查这个线程是否被预置了未捕获异常处理器。如果找到,JVM将调用线程对象的这个方法,并将线程对象和异常作为传入参数。如果线程没有被预置未捕获异常处理器,JVM将打印堆栈记录到控制台,并退出程序。
- 首先,他查找线程对象的未捕获异常处理器。
- 如果找不到,JVM继续查找线程对象所在的线程组的未捕获异常处理器。
- 如果还是找不到,JVM将继续查找默认的未捕获异常处理器。
- 如果没有一个处理器存在,JVM则将堆栈异常记录打印到控制台,并退出程序。
9.线程局部变量的使用
import java.util.Date;import java.util.concurrent.TimeUnit;public class SafeTask implements Runnable {private static ThreadLocal<Date> startDate = new ThreadLocal<Date>() {protected Date initialValue(){return new Date();}};@Overridepublic void run() {// TODO Auto-generated method stubSystem.out.println("Starting Thread: "+Thread.currentThread().getId()+" : "+startDate.get());try {TimeUnit.SECONDS.sleep((int)(Math.rint(Math.random()*10)));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("Thread Finished: "+Thread.currentThread().getId()+" : "+startDate.get());}}线程局部变量分别为每个线程存储了各自的属性值,并提供给每个线程使用。你可以使用get()方法读取这个值,并用set()方法设置这个值。如果线程是第一次访问线程局部变量,线程局部变量可能还没有为他存储值,这个时候initialValue()方法就会被调用,并且返回当前的时间值。
10.线程的分组
public class Result {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}
import java.util.Date;import java.util.Random;import java.util.concurrent.TimeUnit;public class SearchTask implements Runnable{private Result result;public SearchTask(Result result) {this.result = result;}@Overridepublic void run() {// TODO Auto-generated method stubString name = Thread.currentThread().getName();System.out.println("Thread "+name+" : Start");try {doTask();result.setName(name);} catch (InterruptedException e) {// TODO Auto-generated catch blockSystem.out.println("Thread "+name+": Interrupted");return;}System.out.println("Thread "+name+" : End");}private void doTask()throws InterruptedException {Random random = new Random(new Date().getTime());int value = (int)(random.nextDouble()*100);System.out.println("Thread "+Thread.currentThread().getName()+" : "+value);TimeUnit.SECONDS.sleep(value);}}
import java.util.concurrent.TimeUnit;public class Main {public static void main(String[] args) {ThreadGroup threadGroup = new ThreadGroup("Searcher");Result result = new Result();SearchTask searchTask = new SearchTask(result);for (int i = 0; i < 5; i++) {Thread thread = new Thread(threadGroup,searchTask);thread.start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println("Number of Threads "+threadGroup.activeCount());System.out.println("Infomation about the Thread Group");threadGroup.list();Thread[] threads = new Thread[threadGroup.activeCount()];threadGroup.enumerate(threads);for (int i = 0; i < threadGroup.activeCount(); i++) {System.out.println("Thread "+threads[i].getName()+" : "+threads[i].getState());}waitFinish(threadGroup);threadGroup.interrupt();}private static void waitFinish(ThreadGroup threadGroup) {while(threadGroup.activeCount()>19) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
11.线程组中不可控异常的处理
public class MyThreadGroup extends ThreadGroup{public MyThreadGroup(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void uncaughtException(Thread t, Throwable e) {System.out.println("The thread "+t.getId()+" has thrown an Exception");e.printStackTrace(System.out);System.out.println("Terminating the rest of the Threads");interrupt();}}
public class Task implements Runnable{@Overridepublic void run() {// TODO Auto-generated method stubint result;Random random = new Random(Thread.currentThread().getId());while(true) {result = 1000/((int)(random.nextDouble()*1000));System.out.println(Thread.currentThread().getId()+" : "+result);if (Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getId()+" : Interrupted");return;}}}}
public class Main {public static void main(String[] args) {MyThreadGroup threadGroup = new MyThreadGroup("MyThreadGroup");Task task = new Task();for (int i = 0; i < 2; i++) {Thread thread = new Thread(threadGroup,task);thread.start();}}}
12.使用工厂类创建线程
- 更容易修改类,或者改变创建对象的方式;
- 更容易为有限资源限制创建对象的数目。例如:我们可以限制一个类型的对象不多于N个
- 更容易为创建的对象生成统计数据
import java.util.ArrayList;import java.util.Date;import java.util.Iterator;import java.util.List;import java.util.concurrent.ThreadFactory;public class MyThreadFactory implements ThreadFactory {private int counter;private String name;private List<String> stats;public MyThreadFactory(String name) {this.counter = 0;this.name = name;this.stats = new ArrayList<String>();}@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r,name+"-Thread_"+counter);counter++;stats.add(String.format("Created thread %d with name %s on %s\n", thread.getId(),thread.getName(),new Date()));return thread;}public String getStats() {StringBuffer buffer = new StringBuffer();Iterator<String> iterator = stats.iterator();while(iterator.hasNext()) {buffer.append(iterator.next());buffer.append("\n");}return buffer.toString();}}
import java.util.concurrent.TimeUnit;public class Task implements Runnable{@Overridepublic void run() {// TODO Auto-generated method stubtry {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
public class Main {public static void main(String[] args) {MyThreadFactory factory = new MyThreadFactory("MyThreadFactory");Task task = new Task();Thread thread;System.out.println("Starting the Threads");for (int i = 0; i < 10; i++) {thread = factory.newThread(task);thread.start();}System.out.println("Factory stats:");System.out.println(factory.getStats());}}ThreadFactory接口只有一个方法,即newThread,他以Runnable接口对象作为传入参数并且返回一个线程对象。当实现ThreadFactory接口时,必须实现覆盖这个方法。大多数基本的线程工厂类只有一行,即: return new Thread(r); 可以增加一些变化来强化实现方法覆盖。
- 创建一个个性化线程,如这个范例中使用一个特殊的格式作为线程名,或者通过继承Thread类来创建自己的线程类。
- 保存新创建的线程的统计数据,如本例。
- 限制创建的线程的数量
- 对生成的线程进行验证
- 线程管理
- 线程管理
- 线程管理
- 线程管理
- 线程管理
- 线程管理
- 线程管理
- 线程管理
- 线程管理
- 线程管理
- 管理线程的线程池
- 管理线程之创建线程
- 管理线程之创建线程
- 【高级线程管理】线程池
- java线程状态管理
- Linux 进程管理--------------------线程
- Win2Linux 线程管理映射
- ACE_Thread_Manager线程管理学习
- Fiddler 从安装到使用 (creation of the root certificate was&n 此博文包含图片
- 回顾build 2016:你好,这是微软迄今最好的Windows开发平台
- FOSS历史回顾:三代开源人的故事
- 关于.NET下开源及商业图像处理(PSD)组件
- 程序员欢呼:微软Bing开始支持搜索源码、可直接运行
- 线程管理
- .NET FM的未来计划
- 第二篇 Entity Framework Plus 之 Query Future
- 第一篇 Entity Framework Plus 之 Audit
- 微软CEO纳德拉恢弘计划:让开发者始终忘不了微软
- Nancy之结合tinyfox给我们的应用提供简单的数据服务
- WEB API系列(一):WEB API的适用场景、第一个实例
- Z.ExtensionMethods 一个强大的开源扩展库
- 鼠标移动div效果:鼠标拖曳效果