线程的中断机制
1.调用Thread.stop()
该方法强迫停止一个线程并抛出新建立的ThreadDeath对象作为异常,停止一个尚未启动的线程是允许的,如果稍后再启动该线程,它会立刻停止。该方法是不安全的,已经不建议再使用,java以后的版本中他将不复存在。
2.调用Thread.interrupt()
中南是一种协作机制,也就是说通过中断,并不能直接通知另一个线程,而需要被中断线程自己处理中断。java模型也可以简单做如下解释,每一个线程对象里都有一个boolen类型的标识符代表着是否有中断请求。当线程t1想中断t2,则需要在t1中将t2对象的中断标志设置true,然后t2可以在适当的时候处理该中断请求,甚至可以不理会该请求,就像线程没有被中断一样。
下面写的代码,说明一下该情况。
public class ThreadInterruptDemo implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
boolean stop = false;
while (!stop) {
System.out.println("the thread is running.....");
long time = System.currentTimeMillis();
while((System.currentTimeMillis()-time<1000)) {
//为了少打印几次
}
}
System.out.println("thread exiting under request....");
}
public static void main(String[] args) {
Thread thread = new Thread(new ThreadInterruptDemo(), "InterruptDemo");
System.out.println("Thread is start...");
thread.start();
try {
Thread.sleep(300L);
System.out.println("Thread Interrupt");
thread.interrupt();
System.out.println("Thread is InperruptS? " + thread.isInterrupted());
Thread.sleep(300L);
System.out.println("stopping....");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
Thread is start...
the thread is running.....
Thread Interrupt
Thread is InperruptS? true
stopping....
the thread is running.....
the thread is running.....
the thread is running.....
。。。。。。。
所以运行结果上可以看到,线程永远没有结束就像我们前面所描述的一样,线程没有处理该中断请求,就像这个线程没有被中断一样。
接下来我们将上面的例子稍作改进添加代码,代码变成了以下内容。
public class ThreadInterruptDemo implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("the thread is running.....");
boolean stop = false;
while (!stop) {
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < 1000) {
// 延时
}
if (Thread.currentThread().isInterrupted()) {
Thread.currentThread();//取得当前线程
//做一些中断处理****
break;
}
}
System.out.println("thread exiting under request....");
}
public static void main(String[] args) {
Thread thread = new Thread(new ThreadInterruptDemo(), "InterruptDemo");
System.out.println("Thread is start...");
thread.start();
try {
Thread.sleep(300);
System.out.println("Thread Interrupt");
thread.interrupt();
System.out.println("Thread is InperruptS? " + thread.isInterrupted());
Thread.sleep(300);
System.out.println("stopping....");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
Thread is start...
the thread is running.....
Thread Interrupt
Thread is InperruptS? true
stopping....
thread exiting under request....
从新的结果上看,线程2真的终止结束 。
线程的生命周期
照例贴图(书上讲的比较清晰)
守护线程
守护进程可以简单的理解为后台进场,当进程结束时守护线程自然而然的会结束,不需要手动的去关心和通知其状态。守护线程与普通线程写法上没有什么区别,调用线程对象的方法setDaemon(true)可以将其设置守护线程,该方法必须在线程启动之前调用。下面写一个代码,说明一下。
public class ThreadMain {
public static void main(String[] args) {
Thread tA = new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("run"+i+"times");
}
}
};
tA.setDaemon(true);
tA.start();
Thread mainthread = Thread.currentThread();
System.out.println("ta is daemo?" + tA.isDaemon());
System.out.println("mainthread is daemo?" + mainthread.isDaemon());
}
}
结果:
ta is daemo?true
run0times
run1times
run2times
run3times
run4times
mainthread is daemo?false
run5times
run6times
run7times
从以上执行结果可以看出,前台线程保证是执行完毕的,后台还没有执行完毕就退出了。
jar判断程序是否执行结束的标准是所有的前台执行线程执行完毕,而不管后台线程的状态,因此在使用后台线程的时候,一定要注意这个问题,
当进程中所有非守护线程已经结束或退出时,仍有守护线程在运行,进程即将结束也就说明当程序结束,守护线程有可能仍然还未退出。
线程组
书中给的也比较模糊,还是贴图吧。
当前线程的副本:ThreadLocal
当时用维护线城市,会为使用该变量的现场提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本,从线程的角度来看目标变量就像是线程本地变量,也就是说local所表示的意思。下面用一个代码说明一下。
public class ThreadLocalDemo {
private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {
protected Integer initialValue() {
return 0;
}
};
public static ThreadLocal<Integer> getSeqNum() {
return seqNum;
}
public Integer getNextNum() {
seqNum.set(seqNum.get() + 1);
return seqNum.get();
}
public static void main(String[] args) {
ThreadLocalDemo sn = new ThreadLocalDemo();
// 产生3个共享变量各自的序号
TestClient t1 = new TestClient(sn);
TestClient t2 = new TestClient(sn);
TestClient t3 = new TestClient(sn);
t1.start();
t2.start();
t3.start();
}
private static class TestClient extends Thread {
private ThreadLocalDemo sn;
public TestClient(ThreadLocalDemo sn1) {
this.sn = sn1;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("thread" + Thread.currentThread().getName() + "--->sn" + sn.getNextNum());
}
sn.getSeqNum().remove();
}
}
}
结果
threadThread-1--->sn1
threadThread-1--->sn2
threadThread-1--->sn3
threadThread-2--->sn1
threadThread-0--->sn1
threadThread-0--->sn2
threadThread-0--->sn3
threadThread-2--->sn2
threadThread-2--->sn3
LocalThread内部的原理:
依然是贴图!!
总结:localthread中有一个hashmap《thread,T》,通过当前线程取出。
线程异常处理
还是贴图吧
public class ExceptionHandlerThreadB implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("An exception has been captured");
System.out.printf("Thread:%s\n",t.getId());
System.out.printf("Exception:%s: %s",e.getClass().getName(),e.getMessage());
System.out.println("Stack Trace:\n");
e.printStackTrace(System.out);
System.out.printf("Thread status: %s\n",t.getState());
}
}
public class ThreadB implements Runnable {
@Override
public void run() {
int number=Integer.parseInt("tt");
}
}
public class threadmain {
public static void main(String[] args) {
ThreadB threadB=new ThreadB();
Thread thread=new Thread(threadB);
thread.setUncaughtExceptionHandler(new ExceptionHandlerThreadB());
thread.start();
}
}
结果:
An exception has been captured
Thread:8
Exception:java.lang.NumberFormatException: For input string: "tt"Stack Trace:java.lang.NumberFormatException: For input string: "tt"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at StartThread.UncaughtException.ThreadB.run(ThreadB.java:7)
at java.lang.Thread.run(Thread.java:745)
Thread status: RUNNABLE
好吧!!这次写的不好,抽时间我赞改改。