Java 线程(Thread类)

使用线程技术多半是为了并发处理效果,单核通过CPU调度模拟多任务。

 

一 基础

    实现1 :继承java.lang.Thread类,重写run()方法实现线程任务。

 

public class SimpleThread extends Thread{
	@Override
	public void run() {
		//线程任务
		for (int i = 0; i < 10; i++) {
			System.out.println("running " + i + " time!");
		}
	}
	
	public static void main(String[] args){
		//启动线程
		new SimpleThread().start();
	}
}

 

    实现2:实现Runnable接口,重写run()方法实现线程任务

   

public class SimpleRunnableTest{
	
	public static void main(String[] args){
		//启动线程
		new SimpleRunnableThread(new Runnable(){

			@Override
			public void run() {
				//线程任务
				for (int i = 0; i < 10; i++) {
					System.out.println("running " + i + " time!");
				}
			}
			
		}).start();
	}
}

 

   最基础的,没啥大价值。提一下,主线程调用线程类的start()方法线程才能启动,期间Java虚拟机做了必要的准备工作。直接调用线程类的run()方法,相当于在主线程中进行方法调用。和线程没啥关系。

 

   两种实现的关系相当下面:

public class SimpleRunnableThread extends Thread{
	private Runnable r;
	public SimpleRunnableThread(Runnable r){
		this.r = r;
	}
	
	@Override
	public void run() {
		if(r!=null){
			r.run();
		}
	}
}

 

二 Thread类方法

 

1)setPriority(int newPriority): 修改线程优先级

2)join():等待线程线程销毁,可以用来等待线程任务结束。

3)sleep():线程休眠指定时间

4)yield():线程暂停,让出资源以供其他线程使用。

5)setDaemon(boolean on):设置线程为后台线程(参数为true),当所有后台线程结束时(如主线程),后台线程会被销毁。

 

演示一下:

public class ThreadMethodTest {
	public static void main(String[] args) throws Exception {

		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				for (int i = 0; i < 100; i++) {
					System.out.println("running " + i + " time!");
				}
			}

		});
		// 设置thread为后台线程,主线程执行完毕,thread会被销毁,不管是否执行完成。
		thread.setDaemon(true);
		thread.start();

		// 主线程暂时暂停,让thread线程跑一会,多久看系统的任务调度
		Thread.yield();
		// 主线程加入等待thread销毁,thread必须是执行完成,销毁后,才能解除调用该部分的block
		//thread.join();

	}

}

 

分析 :

1)设置了thread为后台线程,所有只要main线程执行结束,thread线程也会被销毁,程序退出。

2)main线程通过 Thread.yield(); 暂停,以供thread线程执行,Thread能执行多久看系统调度分配。每次输出基本不同。

3)注释掉的 thread.join(); 可以等待thread线程执行完。

 

三 一种停止循环任务的策略

   线程时常用于执行循环任务,直到程序发出结束通知。为防止线程在标志位改变时正在休眠,不能立即结束退出,一般采用设置标志位和InterruptedException 一起使用的方案。

public class StopThreadTest implements Runnable {
	private boolean allowRun = true;
	private Thread mThread;

	@Override
	public void run() {
		while (allowRun) {
			try {
				System.out.println("Thread do work!");
				Thread.sleep(5000);
			} catch (InterruptedException e) {
			}
		}
		System.out.println("Thread work stop!");
	}

	public void start() {
		if (mThread == null) {
			allowRun = true;
			mThread = new Thread(this);
			mThread.start();
		}
	}

	public void stop() {
		if (mThread != null) {
			//首先设置标志位,当线非休眠执行任务状态时正常退出。
			allowRun = false;
			//如果线程休眠状态,通过InterruptedException退出
			mThread.interrupt();
			mThread = null;
		}
	}

	public static void main(String[] args) throws Exception {
		StopThreadTest test = new StopThreadTest();
		test.start();
		Thread.sleep(1000);
		test.stop();
	}

}

 

 四 线程状态转换

 

 摘自《Java多线程设计模式》,对线程控制很有帮助。

 图片来源:http://blog.****.net/yuan22003/article/details/6754504

 

Java 线程(Thread类)

 

 

 六 可暂停的线程

 

 做了个可暂停的线程,某些场景比较有用。

 

class AdvancedThread extends Thread {
	private boolean allowRun;
	private boolean isPaused;

	private Object lock = new Object();

	// 启动
	public synchronized void startJob() {
		if (getState() == Thread.State.NEW) {
			allowRun = true;
			isPaused = false;
			start();
		}
	}

	@Override
	public void run() {
		super.run();
		try {
			while (allowRun) {
				while (isPaused) {
					synchronized (lock) {
						// 加入lock对象的等待队列,等待直到其他线程调用lock对象的notify()或notifyAll().
						// 约定,使用哪个对象的wait(),必须获得给对象的Monitor(通过synchronized获得),否则会抛出IllegalMonitorStateException
						lock.wait();
					}
				}
				System.out.println(Thread.currentThread() + " running!");
			}
		} catch (InterruptedException e) {
			// 强制停止方法
		}
	}

	// 暂停
	public synchronized void pauseJob() {
		if (!isPaused) {
			isPaused = true;
			System.out.println(Thread.currentThread() + " paused!");
		}
	}

	// 恢复
	public synchronized void resumeJob() {
		if (isPaused) {
			isPaused = false;
			synchronized (lock) {
				// 约定,使用哪个对象的notify(),必须获得给对象的Monitor,否则会抛出IllegalMonitorStateException
				lock.notifyAll();
			}
			System.out.println(Thread.currentThread() + " resumed!");
		}
	}

	/**
	 * 线程停止的条件:非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run
	 * 方法之外的异常。
	 */
	public synchronized void stopJob() {
		if (getState() != Thread.State.NEW
				&& getState() != Thread.State.TERMINATED) {
			allowRun = false;
			// 中断线程。
			/*
			 * 如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int)
			 * 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或
			 * sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个
			 * InterruptedException。
			 * 
			 * 如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个
			 * ClosedByInterruptException。 本除用于强制停止等待的线程
			 */
			interrupt();
			System.out.println(Thread.currentThread() + " stopped!");
		}

	}
}