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。
六 可暂停的线程
做了个可暂停的线程,某些场景比较有用。
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!");
}
}
}