每个线程或者实现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,