一个线程的生命周期:
新状态:一个新产生的线程从新状态开始了它的生命周期。它保持这个状态知道程序start这个线程。
运行状态:当一个新状态的线程被start以后,线程就变成可运行状态,一个线程在此状态下被认为是开始执行其任务。
就绪状态:当一个线程等待另外一个线程执行一个任务的时候,该线程就进入就绪状态。当另一个线程给就绪状态的线程发送信号时,该线程才重新切换到运行状态。
休眠状态:由于一个线程的时间片用完了,该线程从运行状态进入休眠状态。当时间间隔到期或者等待的时间发生了,该状态的线程切换到运行状态。
终止状态:一个运行状态的线程完成任务或者其他终止条件发生,该线程就切换到终止状态。
每当我们用java命令运行一个类时,实际上就会启动一个JVM,而每个JVM在操作系统中就是一个进程。一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。在该类中启动的每个线程都存在于该进程中。而每次运行时至少启动2个线程,一个是main线程,一个是垃圾回收线程。
创建一个线程:
继承Thread类:
public class TestThread extends Thread { private String name; public TestThread(String name) { this.name = name; } public void run() { for (int i = 0; i < 500; i++) { System.out.println(name + ":" + i); } } public static void main(String[] args) { TestThread t1 = new TestThread("A"); TestThread t2 = new TestThread("B"); t1.start(); t2.start(); } }
我们调用了start方法,而没有直接调用run方法,原因是start会调用本地操作系统的函数。下面是start的源码:
public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } } } private native void start0();
start0使用了native关键字,正面是调用了系统的函数。start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。
实现Runnable接口:
public class TestRunnable implements Runnable { private String name; public TestRunnable(String name) { this.name = name; } @Override public void run() { for (int i = 0; i < 500; i++) { System.out.println(name + ":" + i); } } public static void main(String[] args) { TestRunnable r1 = new TestRunnable("C"); Thread t1 = new Thread(r1); TestRunnable r2 = new TestRunnable("D"); Thread t2 = new Thread(r2); t1.start(); t2.start(); } }
实现Runnable接口比继承Thread类所具有的优势:
1.适合多个相同的程序代码的线程去处理同一个资源
2.可以避免java中的单继承的限制
3.增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
资源共享demo:
public class TicketManager() { public static void main(String[] args) { TicketWindow tw = new TicketWindow(); Thread t1 = new Thread(tw, "win1"); Thread t2 = new Thread(tw, "win2"); Thread t3 = new Thread(tw, "win3"); } } class TicketWindow() implements Runnable { private int ticket = 500; @Override public void run() { for (int i = 0; i < 1000; i ++) { if (this.ticket > 0) { System.out.println(Thread.currentThread().getName() + " sell ticket number is " + this.ticket--); } } } }
demo模拟一个售票大厅,窗口win1、win2、win3都卖同一种票ticket。我们用三个线程模拟3个窗口,共享资源ticket在类TicketWindow中。实现Runnable更容实现资源的共享。
线程的优先级:
每一个Java线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。Java优先级在MIN_PRIORITY(1)和MAX_PRIORITY(10)之间的范围内。默认情况下,每一个线程都会分配一个优先级NORM_PRIORITY(5)。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器时间。然而,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
Thread方法:
下表列出了Thread类的一些重要方法:
哇塞,居然是沙发?留个名