Java多线程基础知识(三)
一. 管道输入/输出流
它和其它文件输入/输出流或网络输入/输出流的不同之处,它主要是线程之间的数据传输,而传输的媒介是内存。
管道输入/输出流主要包含四中实现:
1. PipedOutputStream, PipedInputStream 面向字节
2. PipedWriter, PipedReader 面向字符
对于Piped类型的流,必须向要进行绑定,需要调用connect()方法,如果没有将输入输出流绑定起来,对于该流的访问会报异常。
package com.bochao.concurrent; import java.io.IOException; import java.io.PipedReader; import java.io.PipedWriter; public class Piped { static class Print implements Runnable { private PipedReader in; public Print(PipedReader in) { this.in = in; } @Override public void run() { int receive = 0; try { while ((receive = in.read()) != -1) { System.out.print((char)receive); } } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { PipedWriter pipedWriter = new PipedWriter(); PipedReader pipedReader = new PipedReader(); try { pipedWriter.connect(pipedReader); } catch (IOException e) { e.printStackTrace(); } // 启动打印线程 Thread thread = new Thread(new Print(pipedReader), "PrintThread"); thread.start(); // int receive = 0; try { while ((receive = System.in.read()) != -1) { pipedWriter.write(receive); } } catch (IOException e) { e.printStackTrace(); } finally { try { pipedWriter.close(); pipedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
二. Thread.join的使用
假设一个线程A调用了thread.join语句,其含义时当前线程A等待thread线程终止之后才从thread.join返回。
package com.bochao.concurrent; import java.util.concurrent.TimeUnit; public class Join { static class Domino implements Runnable{ private Thread thread; public Domino(Thread thread){ this.thread = thread; } @Override public void run() { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " terminate."); } } public static void main(String[] args) throws InterruptedException { Thread previous = Thread.currentThread(); for(int i = 0; i<10; i++){ Thread thread = new Thread(new Domino(previous), String.valueOf(i)); thread.start(); // 接力 previous = thread; } TimeUnit.SECONDS.sleep(5); System.out.println(Thread.currentThread().getName() + " terminate."); } }
三. ThreadLocal 的使用
即线程变量,是一个以ThreadLocal对象为键,任意对象为值得存储结构。这个对象被附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。
通过set(T) 设置一个值,在通过get()方法获取到原先设置的值。
package com.bochao.concurrent; import java.util.concurrent.TimeUnit; public class Profiler { // 第一次get()方法调用时会进行初始化(如果set()方法没有调用),每个线程会调用一次 private static final ThreadLocal<Long> TIME_THREADLOCAL = new ThreadLocal<Long>(){ @Override protected Long initialValue() { return System.currentTimeMillis(); } }; public static final void begin(){ TIME_THREADLOCAL.set(System.currentTimeMillis()); } public static final long end(){ return System.currentTimeMillis() - TIME_THREADLOCAL.get(); } public static void main(String[] args) throws InterruptedException { Profiler.begin(); TimeUnit.SECONDS.sleep(2); System.out.println("Cost: " + Profiler.end() + " mills!"); } }