java并发编程从入门到精通----2.认识java中的Thread(下)

线程的中断机制

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
 

好吧!!这次写的不好,抽时间我赞改改。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值