线程实践
线程的创建
方式一
public class HelloThread extends Thread {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
方式二
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
线程启动和停止
启动线程
调用start方法
停止线程
线程自带的stop方法,一方面已经过时,另一方面,不会对停止的线程做状态保存,使得线程中涉及的对象处于未知状态,如果这些状态,其他线程也会使用,将会使得其他线程出现无法预料的异常,所以,停止程序的功能,需要自己实现。
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
StopThread thread = new StopThread();
thread.start();
Thread.sleep(1000L);
thread.stop();
while (thread.isAlive()) { }
thread.print();
}
private static class StopThread extends Thread {
private int x = 0; private int y = 0;
@Override
public void run() {
synchronized (this) {
++x;
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
++y;
}
}
public void print() {
System.out.println("x=" + x + " y=" + y);
}
}
}
上述代码中,run方法里是一个同步的原子操作,x和y必须要共同增加,然而这里如果调用thread.stop()方法强制中断线程,输出如下:
x=1 y=0
没有异常,也破坏了我们的预期。如果这种问题出现在我们的程序中,会引发难以预期的异常。因此这种不安全的方式很早就被废弃了。
public class MyRunnable implements Runnable {
private boolean doStop = false;
public synchronized void doStop() {
this.doStop = true;
}
private synchronized boolean keepRunning() {
return this.doStop == false;
}
@Override
public void run() {
while(keepRunning()) {
// keep doing what this thread should do.
System.out.println("Running");
try {
Thread.sleep(3L * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
调用
public class MyRunnableMain {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
try {
Thread.sleep(10L * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
myRunnable.doStop();
}
}
上面例子修改
线程进入 run() 方法,并首先检查 keepRunning() 方法的返回值。由于 doStop 初始化为 false,keepRunning() 返回 true,因此线程继续执行。
线程执行 ++x; 后,进入 Thread.sleep(3000L); 的休眠状态。与此同时,主线程执行 Thread.sleep(1000L);,休眠1秒后唤醒,然后调用 thread.doStop();。
然而,thread.doStop(); 只是将 doStop 设置为 true,并不会立即中断正在休眠的线程。线程 StopThread 仍然处于休眠状态,直到3秒后自然唤醒。
当线程唤醒后,它会继续执行 ++y;,因为虽然 doStop() 已经被调用,但是线程是在 synchronized 块内部休眠的,所以在休眠结束并且线程重新获得锁之后,它会继续执行 synchronized 块内的剩余代码。
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
StopThread thread = new StopThread();
thread.start();
Thread.sleep(1000L);
thread.doStop();
while (thread.isAlive()) { }
thread.print();
}
private static class StopThread extends Thread {
private boolean doStop = false;
public synchronized void doStop() {
this.doStop = true;
}
private synchronized boolean keepRunning() {
return this.doStop == false;
}
private int x = 0; private int y = 0;
@Override
public void run() {
if (keepRunning()) {
synchronized (this) {
++x;
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
++y;
}
}
}
public void print() {
System.out.println("x=" + x + " y=" + y);
}
}
}