您的位置:首页 > 其它

第一章 Thread Management(线程管理) 上

2017-08-11 16:05 337 查看

涉及内容:

创建和运行一个线程
获取和设置线程信息
打断一个线程
控制打断的线程
休眠和唤醒线程
等待线程的终止
创建和运行守护线程
处理线程中不受控制的异常
使用local thread变量
将线程加入组
处理线程组的不受控制的异常
通过工厂创建线程

1、简介

并发(concurrency):多线程运行在单核处理器,执行顺序--无序

并行(parallelism) :多线程运行在多核处理,执行顺序--有序

2、创建和运行一个线程

创建一个线程的方法:

继承Thread类
实现Runnable接口,然后创建以Runable对象为参数的Thread对象

这个例子将会使用实现Runnable接口来实现多线程,创建和运行10个线程。每个线程计算和打印一到十的乘积。

public class Calculator implements Runnable{

private int number;

public Calculator(int number) {
super();
this.number = number;
}

public void run() {

for(int i=1; i <= 10; i++){
System.out.printf("%s: %d * %d = %d\n",
Thread.currentThread().getName(),number,i,i*number);
}

}

public static void main(String[] args) {
for(int i=1; i<=10; i++){
Calculator calculator = new Calculator(i);
Thread thread = new Thread(calculator);
thread.start();
}
}
}日志:



总结:

1、当调用start()方法将会创建一个执行线程
2、只要一个线程调用System.exit(),所有线程结束,程序终止

2、获取和设置线程的信息

线程的属性:

ID: 唯一标识每个线程

Name: 线程的名称

Priority:线程的优先级(从1到10) 最低1,最高10。不在这个范围会抛出异常

Status : 线程的状态(六种状态:创建,运行,阻塞,等待,时间等待,终止)

例子:创建十个线程,并设置它的优先级和名称,然后展示它的状态信息。当然它也会计算乘积。

package com.jack;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.Thread.State;

public class Calculator implements Runnable{

private int number;

public Calculator(int number) {
super();
this.number = number;
}

public void run() {

for(int i=1; i <= 10; i++){
System.out.printf("%s: %d * %d = %d\n",
Thread.currentThread().getName(),number,i,i*number);
}

}

public static void main(String[] args) throws IOException {
Thread [] threads = new Thread[10];
Thread.State [] status = new Thread.State[10];

for (int i=0; i<10; i++){
threads[i] = new Thread(new Calculator(i));
if((i % 2) == 0) {
threads[i].setPriority(Thread.MAX_PRIORITY);
} else {
threads[i].setPriority(Thread.MIN_PRIORITY);
}
threads[i].setName("Thread " + i);
}
try (FileWriter file = new FileWriter("D:\\\\\\data\\log.txt");
PrintWriter pw = new PrintWriter(file);){
for (int i=0; i<10; i++) {
pw.println("Main: Status of Thread " + i + " : " +
threads[i].getState());
status[i] = threads[i].getState();
}

for (int i=0; i<10; i++){
threads[i].start();
}
boolean finish = false;
while(!finish) {
for (int i=0; i<10; i++) {
if (threads[i].getState() != status[i]) {
writeThreadInfo(pw, threads[i], status[i]);
status[i] = threads[i].getState();
}
}
finish = true;
//判读所有线程是否结束
for(int i=0; i<10; i++) {
finish = finish && (threads[i].getState() == State.TERMINATED);
}
}
}
}

private static void writeThreadInfo(PrintWriter pw, Thread thread, State state) {
pw.printf("Main : Id %d - %s\n", thread.getId(), thread.getName());
pw.printf("Main : Priority: %d\n", thread.getPriority());
pw.printf("Main : Old State: %s\n", state);
pw.printf("Main : New State : %s\n", thread.getState());
pw.printf("Main : *********************************\n");
}
}


日志:



总结:
1、打印状态语句块不一定是10整数倍,因为在执行打印状态的时候程序线程,有些状态没有第二次没有改变而被过滤了。
2、循环打印状态直到所有线程都终止,这里用了FileWriter(注意要确认文件夹是否存在,否则抛出异常)和PrintWriter
3、并不是优先级高一定先执行完,只是有概率是靠前的。
4、不能修改ID和status属性。
5、线程默认值的名称为Thread-XX(XX是一个数字)

3、打断一个线程

创建一个线程,通过interruption mechanism(打断机制)5秒之后将会强迫finalization。

public class PrimeGenerator extends Thread{

@Override
public void run() {
long number = 1L;
while(true) {
if (iPrime(number)) {
System.out.printf("数字 %d 是 素数 \n", number);
}
if(isInterrupted()){
System.out.printf("素数生成器已经打断了");
return;
}
number ++;
}
}

private boolean iPrime(long number) {
if(number <=2 ) {
return true;
}
for (long i=2; i<number; i++){
if((number % i) == 0){
return false;
}
}
return true;
}

public static void main(String[] args){
Thread task = new PrimeGenerator();
task.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e){
e.printStackTrace();
}
task.interrupt();
}

}


日志:



总结:

1、生成数字越大,说明你计算机计算能力越强,哈哈
2、interrupt()方法将会设置属性为true,而isInterrupted()方法只是返回这个属性的值。
3、interrupt()是static 方法, isInterrupted()不是static方法

4、控制线程的打断情况

实现用确定的名称在文件夹以及子目录下查找文件来学习InterruptedException异常的控制

import java.io.File;
import java.util.concurrent.TimeUnit;

public class FileSearch implements Runnable{

private String initPath;
private String fileName;

public FileSearch(String initPath, String fileName) {
super();
this.initPath = initPath;
this.fileName = fileName;
}

@Override
public void run() {
File file = new File(initPath);
if(file.isDirectory()) {
try{
directoryProcess(file);
} catch (InterruptedException e){
System.out.printf("%s: 搜索已经被中断了", Thread.currentThread().getName());
}
}

}

private void directoryProcess(File file) throws InterruptedException {
File list[] = file.listFiles();
if(list != null) {
for (int i=0; i <list.length; i++) {
if(list[i].isDirectory()) {
directoryProcess(list[i]);
}else {
fileProcess(list[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();
}

}

public static void main(String[] args) {
FileSearch sercher = new FileSearch("D:\\360Downloads", "filelist.dat");
Thread thread = new Thread(sercher);
thread.start();

try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}

总结:

1、如果在10秒内找完所有文件和目录将不会抛出异常(不管找到文件有没有)。
2、InterruptedException抛出与一些API方法有关例如,sleep()
3、学习新的休眠方法,TimeUnit类的方法。
4、利用递归查询文件夹与文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: