1.线程的创建、运行和设置
Calculator类
存放线程将要运行的指令:计算20000以内的素数
package com.company.ConcurencyCookbook;
/**
* 线程的创建设置与运行
*/
public class Calculator implements Runnable{
@Override
public void run() {
long cureent = 1L;
long max = 20000L;
long numPrimes = 0L;
System.out.printf("Thread '%s' is start\n",Thread.currentThread().getName());
while (cureent<=max){
if(isPrime(cureent)){
numPrimes++;
}
cureent++;
}
System.out.printf("Thread '%s' :End. Number of Prime : %d\n",Thread.currentThread().getName(),numPrimes);
}
//判断是否是质数
private boolean isPrime(long number){
if(number<=2){
return true;
}
for(long i=2;i<number;i++){
if((number%i)==0){
return false;
}
}
return true;
}
}
Main类
包含main方法的Main类:输出线程的最大值、最小值、默认优先级,创建10个线程对象,执行Calculator任务,创建保存Thread对象和State对象的数组,对5个线程设置最大优先级,对5个线程对象设置最小优先级。
package com.company.ConcurencyCookbook;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;
public class Main{
/**
* Calculator类实现
* 线程的创建、运行和设置
* 多线程设置优先级完成对素数的统计
*/
public static void main(String[] args){
System.out.printf("Mininum Priority: %s\n",Thread.MIN_PRIORITY);
System.out.printf("Normal Priority: %s\n",Thread.NORM_PRIORITY);
System.out.printf("Maxinum Priority: %s\n",Thread.MAX_PRIORITY);
Thread[] threads;
Thread.State[] status;
threads = new Thread[10];
status = new Thread.State[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(new Calculator());
if(i%2==0){
threads[i].setPriority(Thread.MAX_PRIORITY);
}else {
threads[i].setPriority(Thread.MIN_PRIORITY);
}
threads[i].setName("My Thread"+i);
}
try(FileWriter file = new FileWriter(".\\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;
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() == Thread.State.TERMINATED);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeThreadInfo(PrintWriter pw, Thread 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");
}
}
输出
2.线程的休眠与唤醒
ConsoleClock类:实现迭代10次的循环,在每次迭代中,创建Date对象,并将其输出至控制台,调用TimeUnit类SECONDS属性的sleep()方法,使当前线程暂停1 秒,sleep()方法会抛出异常。
package com.company.ConcurencyCookbook;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* 线程的休眠与唤醒
*/
public class ConsoleClock implements Runnable {
@Override
public 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");
}
}
}
}
Main类
创建ConsoleClock对象和执行该对象的线程,执行线程
package com.company.ConcurencyCookbook;
import java.util.concurrent.TimeUnit;
public class Main{
/**
* ConsoleLLock类实现
* 线程的休眠和唤醒
*/
public static void main(String[] args){
ConsoleClock consoleClock = new ConsoleClock();
Thread thread =new Thread(consoleClock);
thread.start();
System.out.println(thread.getState());
try{
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}
输出
3.创建守护线程
Event类
存储程序中使用的事件信息,声明两个私有属性,一个是java.util,Date类型的date,一个是String类型的属性event。
package com.company.ConcurencyCookbook.daemonThread;
import java.util.Date;
/**
* 守护线程
* 存储程序中所使用的事件信息
*/
public class Event {
private Date date;
private String event;
public Event(){}
public Event(Date date,String event){
this.date = date;
this.event = event;
}
public void setDate(Date date){
this.date = date;
}
public void setEvent(String event){
this.event = event;
}
public Date getDate(){
return this.date;
}
public String getEvent (){
return this.event;
}
}
WriteeTasl类
声明一个存储事件的队列。包含100次迭代循环,在每一次迭代中,创建一个新的事件并将其存储到队列中,并休眠1秒。
package com.company.ConcurencyCookbook.daemonThread;
import java.util.Date;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
/**
* 储存事件的队列
*/
public class WriterTask implements Runnable {
private Deque<com.company.ConcurencyCookbook.daemonThread.Event> deque;
public WriterTask (Deque<com.company.ConcurencyCookbook.daemonThread.Event> deque){
this.deque = deque;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
com.company.ConcurencyCookbook.daemonThread.Event event = new Event(new Date(), String.format("The Thread %s has generated an event",Thread.currentThread().getId()));
deque.addFirst(event);
try{
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
CleanerTask类
获取队列中的最后一个事件,如果该事件创建了10秒,则从队列中农删除该事件并检查下一个事件,如果删除该事件,则输出该事件的信息以及队列的大小。
package com.company.ConcurencyCookbook.daemonThread;
import java.util.Date;
import java.util.Deque;
public class CleanerTask extends Thread {
private Deque<Event> deque;
public CleanerTask(Deque<Event> deque){
this.deque = deque;
setDaemon(true);
}
@Override
public void run() {
while (true){
Date date = new Date();
clean(date);
}
}
private void clean(Date date){
long difference;
boolean delete;
if (deque.size()==0){
return;
}
delete = false;
do {
Event e =deque.getLast();
difference = date.getTime() - e.getDate().getTime();
if (difference > 10000){
System.out.printf("Cleaner: %s\n",e.getEvent());
deque.removeLast();
delete = true;
}
}while (difference>10000);
if (delete){
System.out.printf("Cleaner: Size of the queue: %d\n",deque.size());
}
}
}
Main类
根据JVM可用处理器个数创建对应数量的线程,执行WriterTask任务,接着创建一个CleanerTask线程任务。
package com.company.ConcurencyCookbook.daemonThread;
import java.util.Deque;
import java.util.concurrent.ConcurrentLinkedDeque;
public class Main {
public static void main(String[] args){
Deque<Event> deque = new ConcurrentLinkedDeque<Event>();
WriterTask writer = new WriterTask(deque);
for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) {
Thread thread = new Thread(writer);
thread.start();
}
CleanerTask cleaner = new CleanerTask(deque);
cleaner.start();
}
}
输出
4.处理线程中的不可控异常
异常:
- 检查异常: 该异常需要在方法的throw语句中声明,或者在方法内部捕获,例如IOException或ClassNotFoundException
- 非检查异常 该异常不需要捕获或者声明,例如NumberFormatException
ExceptionHandler
实现处理非检查异常的类
package com.company.ConcurencyCookbook.ExceptionUnCheck;
public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.printf("An exception has been captured\n");
System.out.printf("Thread: %s\n",t.getId());
System.out.printf("Exception:%s: %s\n",e.getClass().getName(),e.getMessage());
System.out.printf("Stack Trace: \n");
e.printStackTrace(System.out);
System.out.printf("Thread status: &s\n",t.getState());
}
}
Task类
用于抛出非检查异常的类Task
package com.company.ConcurencyCookbook.ExceptionUnCheck;
public class Task implements Runnable {
@Override
public void run() {
int numero = Integer.parseInt("TT");
}
}
Mian类
创建Task对象,使用线程执行该对象,为线程设置非检查异常处理器
package com.company.ConcurencyCookbook.ExceptionUnCheck;
public class Main {
public static void main(String[] args){
Task task = new Task();
Thread thread = new Thread(task);
thread.setUncaughtExceptionHandler(new ExceptionHandler());
thread.start();
}
}