Thread t1 = new Thread();
t1.start();
也可以用Runnable接口新建线程,它只有一个run()方法,而且默认的Thread.run()就是调用内部的Runnable接口,因此使用Runnable更合理。
public interface Runnable {
public abstract void run();
}
Thread类有一个构造方法:
public Thread(Runnable target)
默认的Thread.start()方法调用的时候,新的线程就会执行Runnable.run()方法:
public void run(){
if(target != null){
target.run();
}
}
以下代码实现Runnable接口,并将该实例传入Thread,避免重载Thread.run():
public class CreateThread implements Runnable{
public static void main(String[] args){
Thread t1 = new Thread(new CreateThread());
t1.start();
}
@Override
public void run(){
System.out.println("Here is a Runnable!");
}
}
一般来说,线程在执行完成之后就会结束。但是也可以手动关闭线程。
例如,以下代码没有错误信息,但是结果不一致了:
public class StopThreadUnsafe {
public static User u = new User();
public static class User {
int id;
String name;
public User() {
id = 0;
name = "0";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id = " + id + ", name = " + name + "]";
}
}
public static class ChangeObjectThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (u) {
int v = (int) (System.currentTimeMillis() / 1000);
u.setId(v);
// do something else
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
u.setName(String.valueOf(v));
}
Thread.yield();
}
}
}
public static class ReadObjectThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (u) {
if (u.getId() != Integer.parseInt(u.getName())) {
System.out.println(u.toString());
}
}
Thread.yield();
}
}
}
public static void main(String[] args) throws InterruptedException {
new ReadObjectThread().start();
while (true) {
ChangeObjectThread t = new ChangeObjectThread();
t.start();
Thread.sleep(150);
t.stop();
}
}
}
如果要安全的停止一个线程,可以自己决定停止线程的时机,例如将前例中的CreateObjectThread线程中增加一个stopMe()方法:
public static class ChangeObjectThread extends Thread {
volatile boolean stopme = false;
public void stopMe() {
stopme = true;
}
@Override
public void run() {
while (true) {
if(stopme) {
System.out.println("exit by stop me");
break;
}
synchronized (u) {
int v = (int) (System.currentTimeMillis() / 1000);
u.setId(v);
// do something else
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
u.setName(String.valueOf(v));
}
Thread.yield();
}
}
}
public void Thread.interrupt() //中断线程
public boolean Thread.isInterrupted() //判断线程是否中断
public static boolean Thread.interrupted() //判断是否中断,并清除当前中断状态
注意:中断后需要增加中断处理代码,不然中断不会发生作用。
在循环体中,出现了sleep()或者wait()等操作,需要通过中断来识别。wait()在下一小节介绍,这里介绍sleep()方法。 Thread.sleep()函数的作用是让当前线程休眠若干时间,其函数签名为:
public static native void sleep(long millis) throws InterruptedException
它会抛出一个InterruptedException异常,不是运行时异常,程序必须捕获并处理他。当线程在sleep()休眠中被中断,这个异常就会产生。 注意:Thread.sleep()方法因为中断抛出异常时,会清除中断标记,如果不加处理,在下一次循环开始时,就无法捕捉这个中断,所以在异常处理中需要再次设置中断标记位。
public final void wait() throws InterruptedException
public final native void notify()
线程调用object.wait()方法,它会进入到object的等待队列。当object.notify()方法被调用时,对象会在线程队列中,随机选择一个线程,将其唤醒。 注意:这个选择是非公平的,完全随机。 使用例子:
package temp;
public class SimpleWN {
final static Object object = new Object();
public static class T1 extends Thread{
public void run() {
//获得object对象锁
synchronized(object) {
System.out.println(System.currentTimeMillis() + ": T1 Start!");
try {
System.out.println(System.currentTimeMillis() + ": T1 is wait for obejct!");
// 释放object的对象锁
object.wait();
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + ": T1 is end");
}
}
}
public static class T2 extends Thread {
public void run() {
synchronized(object) {
System.out.println(System.currentTimeMillis() + ": T2 Start!");
System.out.println("notify one thread!");
// 释放object对象锁
object.notify();
System.out.println(System.currentTimeMillis() + ": T2 end!");
try {
// 休眠结束之后,才释放对象锁,T1才能继续执行
Thread.sleep(2000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread t1 = new T1();
Thread t2 = new T2();
t1.start();
t2.start();
}
}
以下例子会导致系统锁死:
public class BadSuspend {
public static Object u = new Object();
static ChangeObjectThread t1 = new ChangeObjectThread("t1");
static ChangeObjectThread t2 = new ChangeObjectThread("t2");
public static class ChangeObjectThread extends Thread{
public ChangeObjectThread(String name) {
super.setName(name);
}
@Override
public void run() {
synchronized(u) {
System.out.println("in " + getName());
Thread.currentThread().suspend();
}
}
}
public static void main(String[] args) throws InterruptedException{
// t1
t1.start();
Thread.sleep(100);
t2.start();
t1.resume();
// 此时t2的状态依然是RUNNABLE
t2.resume();
t1.join();
t2.join();
}
}
为了达到相同的目的,可以用如下方法(使用wait()和notify()):
public class GoodSuspend {
public static Object u = new Object();
public static class ChangeObjectThread extends Thread{
// 标记变量,表明线程是否被挂起
volatile boolean suspendme = false;
public void suspendMe() {
suspendme = true;
}
public void resumeMe() {
suspendme = false;
synchronized (this){
notify();
}
}
@Override
public void run() {
while(true) {
synchronized(this) {
// 检查线程是否被挂起
while(suspendme) {
try{
wait();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized(u) {
System.out.println("in ChangeObjectThread");
}
Thread.yield();
}
}
}
public static class ReadObjectThread extends Thread{
@Override
public void run() {
while(true) {
synchronized(u) {
System.out.println("in ReadObjectThread");
}
Thread.yield();
}
}
}
public static void main(String[] args) throws InterruptedException{
// 实例化线程对象
ChangeObjectThread t1 = new ChangeObjectThread();
ReadObjectThread t2 = new ReadObjectThread();
// 运行线程对象
t1.start();
t2.start();
Thread.sleep(1000);
// 挂起t1线程
t1.suspendMe();
System.out.println("suspend t1 2 sec");
Thread.sleep(2000);
System.out.println("resume t1");
t1.resumeMe();
}
}
// 阻塞当前线程,直到目标线程执行完毕
public final void join() throws InterruptedException
// 最多等待millies毫秒,之后继续执行
public final synchronised void join(long millis) throws InterruptedException
while(isAlive()){
wati(0);
}
基础join()例子:
package temp;
public class JoinMain {
public volatile static int i = 0;
public static class AddThread extends Thread {
@Override
public void run() {
for (; i < 1000000; i++)
;
}
}
public static void main(String[] args) throws InterruptedException {
AddThread at = new AddThread();
System.out.println(i);
at.start();
System.out.println(i);
at.join();
// join()保证最后输出的是1000000
System.out.println(i);
}
}