【Java基础】线程笔记——ThreadApi
2017-03-24 13:42
507 查看
线程的中断机制
第一种方法: Thread.stop() (已废弃)【缺点】线程不安全,已不再使用
第二种方法: Thread.interrupt()
当一个线程运行时,另一个线程可以调用对应的 Thread 对象的 interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回。
如果只是单纯的调用 interrupt()方法,线程并没有实际被中断,会继续往下执行
public class InteruptThread implements Runnable { @Override public void run() { boolean stop = false; while(!stop){ System.out.println("This Thread is Running ......"); long time = System.currentTimeMillis(); while((System.currentTimeMillis() - time < 1000)){ } //当interrupt=true时,需要去处理它的中断状态,不然线程会一直运行 if(Thread.currentThread().isInterrupted()){ Thread.currentThread().interrupt(); break; } } System.out.println("This Thread Exit Under Request"); } }
运行
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new InteruptThread(),"Interupt"); System.out.println("InteruptThread starting ..."); t.start(); Thread.sleep(3000); System.out.println("InteruptThread interupted"); t.interrupt(); System.out.println("线程是否中断---->"+t.isInterrupted()); Thread.sleep(3000); System.out.println("Stop Application"); }
console
InteruptThread starting ... This Thread is Running ...... This Thread is Running ...... This Thread is Running ...... InteruptThread interupted 线程是否中断---->true This Thread Exit Under Request Stop Application
如果去掉if语句判断去处理中断状态,线程一直会一直运行(形成死循环)
InteruptThread starting ... This Thread is Running ...... This Thread is Running ...... This Thread is Running ...... InteruptThread interupted 线程是否中断---->true This Thread is Running ...... This Thread is Running ...... This Thread is Running ...... Stop Application This Thread is Running ...... This Thread is Running ......
注意:一定要对Thread.isInterrupted()状态进行处理
补充(yield()和join()使用)
join 方法用线程对象调用,如果在一个线程 A 中调用另一个线程 B 的 join 方法,线程 A 将会等待线程 B 执行完毕后再执行。yield 可以直接用 Thread 类调用,yield 让出 CPU 执行权给同等级的线程,如果没有相同级别的线程在等待 CPU 的执行权,则该线程继续执行。
守护线程(后台运行线程)
守护线程不需要关心它何时结束,进程结束,守护线程自动结束不要在守护线程中执行业务逻辑操作(比如对数据的读写等)
必须在启动线程前标记守护线程
setDeamon(true);
Java垃圾回收、内存管理就是一个守护线程
注意
setDaemon(true)必须在调用线程的 start()方法之前设置,否则会跑出 IllegalThreadStateException 异常。
在守护线程中产生的新线程也是守护线程。
不要认为所有的应用都可以分配给守护线程来进行服务,比如读写操作或者计算逻辑
线程阻塞
当线程执行 Thread.sleep()时,它一直阻塞到指定的毫秒时间之后,或者阻塞被另一个线程打断;当线程碰到一条 wait()语句时,它会一直阻塞到接到通知(notify())、被中断或经过了指定毫秒时间为止(若制定了超时值的话)
线程阻塞与不同 I/O 的方式有多种。常见的一种方式是 InputStream的read()方法,该方法一直阻塞到从流中读取一个字节的数据为止,它可以无限阻塞,因此不能指定超时时间;
线程也可以阻塞等待获取某个对象锁的排他性访问权限(即等待获得 synchronized 语句必须的锁时阻塞)。
线程组
方便管理线程,并且可以为某些线程设置相同特定的属性例如:setDeamon()、设置未处理异常的处理方法、设置统一的安全策略等
每个ThreadGroup都可以包含一组子线程或者一组子线程组
在一个进程中线程组是以树形存在
system线程组是所有线程的顶级父线程组
//获取当前线程的线程组 Thread.currentThread().getThreadGroup()
Java中允许对一个线程组中所有线程进行操作
Java多线程另一个重要的特性就是线程安全。线程组机制允许通过分组来区分不同特性的线程
线程池和线程组区别:线程组方便管理线程对象。线程池管理线程的声明周期,复用线程,减少创建销毁进程的开销
线程安全
当前线程副本ThreadLocal
ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立的改变自己的副本(Local想表达的意思)remove() 是jdk5以后新增的方法,java会自动垃圾回收变量,调用该方法加快垃圾回收的速度
get()/set() 得到/设置ThreadLocal的值
-initialValue() 返回变量的初始值,只执行一次。若缺省,直接返回一个null
public class ThreadLocalValue { private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){ protected Integer initialValue() {return 0;}; }; public Integer nextNum(){ seqNum.set(seqNum.get() + 1); return seqNum.get(); } public ThreadLocal<Integer> getThreadLocal(){ return seqNum; } }
运行
public static void main(String[] args) { ThreadLocalValue value = new ThreadLocalValue(); TestClient t1 = new TestClient(value); TestClient t2 = new TestClient(value); TestClient t3 = new TestClient(value); t1.start(); t2.start(); t3.start(); } static class TestClient extends Thread{ private ThreadLocalValue tlv = null; public TestClient(ThreadLocalValue tlv){ this.tlv = tlv; } @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("thread["+Thread.currentThread().getName()+"] ---> value : "+tlv.nextNum()); } tlv.getThreadLocal().remove(); } }
console
thread[Thread-2] ---> value : 1 thread[Thread-1] ---> value : 1 thread[Thread-0] ---> value : 1 thread[Thread-1] ---> value : 2 thread[Thread-2] ---> value : 2 thread[Thread-1] ---> value : 3 thread[Thread-0] ---> value : 2 thread[Thread-0] ---> value : 3 thread[Thread-2] ---> value : 3
上面可得出
所产生的序号虽然共享一个实例,但是没用互相干扰,而是各自独立产生序列号,确定每个线程单独提供了一个变量副本
源码解析
set
1.首先通过getMap(t)得到当前相关ThreadLocalMap,将值放入map中,如果为空则重新创建Map createMap(t,value)
ThreadLocalMap 是线程隔离的核心,它是ThreadLocal的静态内部类,实现了键值对的设置和获取(对比Map) 存储的值,只能被当前线程读取和修改,ThreadLocal操作每个线程特有的ThreadLocalMap,从而实现了变量在不同线程中的隔离
ThreadLocalMap的键的this对象指的就是ThreadLocal,值就是所存储的值。
static class ThreadLocalMap
总结
ThreadLocal处理线程的局部变量,要比synchronized同步机制解决线程问题更简单,更方便,而且结果程序拥有更高的并发性线程的异常处理
所有异常必须在run方法进行处理,不能抛出throw exception方法一:在try…catch内处理
方法二:实现一个UncaughtExceptionHandler接口
处理unchecked异常
设计一个异常线程B
public class ThreadB implements Runnable { @Override public void run() { int num = Integer.parseInt("A"); System.out.println(num); System.out.println("This is Exception Thread B "); } }
处理线程异常
public class ExceptionOfThreadB implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("Thread -->"+t.getName()+"("+t.getId()+")"); System.out.println("Thread Exception -->"+e.getClass().getName()); System.out.println("exception message -->"+e.getMessage()); System.out.println("state -->" + t.getState()); } }
运行
public static void main(String[] args) { ThreadB threadException = new ThreadB(); Thread t = new Thread(threadException,"threadException"); //设置异常 t.setUncaughtExceptionHandler(new ExceptionOfThreadB()); t.start(); }
console
Thread -->threadException(10) Thread Exception -->java.lang.NumberFormatException exception message -->For input string: "A" state -->RUNNABLE
相关文章推荐
- 【Java基础学习笔记】Thread+JLabel实现线程
- java线程基础巩固---Thread API综合实战之编写ThreadService实现暴力结束线程
- Java基础笔记三线程和String类
- java基础学习笔记之九--线程(3)
- java线程基础——笔记
- Thinking in Java学习笔记,简单包装Thread,实现快速实现线程
- java基础学习笔记之九--线程(2)
- 黑马程序员java基础线程章节笔记
- JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)
- [Java基础] Java线程复习笔记
- Java 学习笔记 (5) - 线程 Thread
- java 从零开始,学习笔记之基础入门<线程及实例分析>(十九)
- 黑马程序员—11—java基础:有关线程通信的学习笔记和学习心得体会
- Java多线程编程总结笔记——一多线程基础知识
- 黑马程序员—17—java基础:有关API的使用学习笔记和心得体会
- 黑马程序员 Java基础学习笔记 线程间同信
- Thinking in Java学习笔记 Thread.UncaughtExceptionHandler接口实现捕获线程内异常
- 【Java基础_(线程篇_第一篇)】继承Thread;实现runnable;sleep、wait用法和区别;Thread和Runnable区别;线程停止