每个线程或者实现Runnable接口再传递给Tread构造,或者直接继承Thread类
前者的优势在于,还可以继承其他的类
Thread.sleep让当前线程休眠一段时间,让步给其他线程或程序
指定的这个时间通常不太精确,另外会被interrupt()中断休眠
中断是说这个线程立即终止目前的工作,但要想正确使用,事先要保证这个线程会抛出中断异常
for (int i = 0; i < importantInfo.length; i++) {
// Pause for 4 seconds
try {
Thread.sleep(4000);//调用的这个方法可以被中断,中断后立即返回
} catch (InterruptedException e) {
// We've been interrupted: no more messages.
return;
}
// Print a message
System.out.println(importantInfo[i]);
}
if (Thread.interrupted()) {//调用这个方法能查询是否被中断了,同时也清除中断状态
throw new InterruptedException();//或者手动抛出然后捕获
}
isInterrupted不会清除中断状态
但任何线程一旦跑出了中断异常,自动解除中断状态
t.join();会让当前线程暂停,等待t线程结束后再恢复,如果t现在正在运行的话
public static void main(String args[])
throws InterruptedException {
// Delay, in milliseconds before
// we interrupt MessageLoop
// thread (default one hour).
long patience = 1000 * 60 * 60;//等待的最长时间
// If command line argument
// present, gives patience
// in seconds.
if (args.length > 0) {
try {
patience = Long.parseLong(args[0]) * 1000;
} catch (NumberFormatException e) {
System.err.println("Argument must be an integer.");
System.exit(1);
}
}
threadMessage("Starting MessageLoop thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
// loop until MessageLoop
// thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second
// for MessageLoop thread
// to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting!");//超过之后
t.interrupt();//强制中断
// Shouldn't be long now
// -- wait indefinitely
t.join();
}
}
threadMessage("Finally!");
}
}
线程间通常通过共享字段来交流,但经常性发生问题,thread interference和memory consistency errors
happens-before关系能够保证某个语句写后的内容在另一个语句读之前就已发生:
1.同一个线程,前一个语句总是在后一个语句之前执行
2.调用另一个线程的Thread.start时,所有之前的语句都会在新线程之前执行
3.一个线程终止时由于另一个线程调用了Thread.join,则任何改变都对另一个线程可见
4.声明为volatile的字段,写总是在读之前
5.同步机制synchronization
一个对象上的同步方法不会被多次调用,而且一次调用的结果总是对下次调用可见
不能对构造方法声明同步,所以构造中如果调用了某个方法,小心多线程错误
声明为final的字段无需用同步方法访问,因为构造后是无法修改的
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
System.out.print(i + ",");
}
System.out.println();
new Thread(new Runnable() {
public void run() {
for (int i = 11; i < 20; i++) {
System.out.print(i + ",");
}
}
}).start();
}
这个输出结果只会是:
0,1,2,3,4,5,6,7,8,9,
11,12,13,14,15,16,17,18,19,