Java9 并发编程实战笔记

    科技2022-08-15  88

    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(); } }

    输出

    Processed: 0.032, SQL: 8