多线程-2.线程创建方式和Thread类
线程的创建方式
1.继承Thread类,重写run方法,示例如下:
1 class PrimeThread extends Thread { 2 long minPrime; 3 PrimeThread(long minPrime) { 4 this.minPrime = minPrime; 5 } 6 7 public void run() { 8 // compute primes larger than minPrime 9 . . . 10 } 11 } 12 PrimeThread p = new PrimeThread(143); 13 p.start();
2.实现Runnable接口,(代理模式)实现run方法,将该对象作为构造参数构造一个Thread类实例,示例如下:
1 class PrimeRun implements Runnable { 2 long minPrime; 3 PrimeRun(long minPrime) { 4 this.minPrime = minPrime; 5 } 6 7 public void run() { 8 // compute primes larger than minPrime 9 . . . 10 } 11 } 12 PrimeRun p = new PrimeRun(143); 13 new Thread(p).start();
线程Thread类及其start()方法和run()方法
1.Java线程的状态
1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
3. 阻塞(BLOCKED):表示线程阻塞于锁。
4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
6. 终止(TERMINATED):表示该线程已经执行完毕。
![](https://img2020.cnblogs.com/blog/2286858/202103/2286858-20210312144420843-291096265.png)
threadStatus源码:
private volatile int threadStatus = 0; public State getState() { // get current thread state return sun.misc.VM.toThreadState(threadStatus); } public static State toThreadState(int var0) { if ((var0 & 4) != 0) { return State.RUNNABLE; } else if ((var0 & 1024) != 0) { return State.BLOCKED; } else if ((var0 & 16) != 0) { return State.WAITING; } else if ((var0 & 32) != 0) { return State.TIMED_WAITING; } else if ((var0 & 2) != 0) { return State.TERMINATED; } else { return (var0 & 1) == 0 ? State.NEW : State.RUNNABLE; } } public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
2.start()方法
start方法的作用就是将线程由NEW状态,变为RUNABLE状态。当线程创建成功时,线程处于NEW(新建)状态,如果你不调用start( )方法,那么线程永远处于NEW状态。调用start( )后,才会变为RUNABLE状态,线程才可以运行。
调用start()方法后,线程是不是马上执行?
线程不是马上执行的;准确来说,调用start( )方法后,线程的状态是“READY(就绪)”状态,而不是“RUNNING(运行中)”状态。线程要等待CPU调度,不同的JVM有不同的调度算法,线程何时被调度是未知的。因此,start()方法的被调用顺序不能决定线程的执行顺序。
注意:
由于在线程的生命周期中,线程的状态由NEW ----> RUNABLE只会发生一次,因此,一个线程只能调用start()方法一次,多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
strat()方法源码:
1 public synchronized void start() { 2 // 如果线程不是"就绪状态",则抛出异常! 3 if (threadStatus != 0) 4 throw new IllegalThreadStateException(); 5 // 将线程添加到ThreadGroup中 6 group.add(this); 7 boolean started = false; 8 try { 9 // 通过start0()启动线程,新线程会调用run()方法 10 start0(); 11 // 设置started标记=true 12 started = true; 13 } finally { 14 try { 15 if (!started) { 16 group.threadStartFailed(this); 17 } 18 } catch (Throwable ignore) { 19 } 20 } 21 }
3.run()方法
run()方法这里只是一个普通的方法,当线程调用了start( )方法后,一旦线程被CPU调度,处于运行状态,那么线程才会去调用这个run()方法。当然,thread示例也可以主动调用run()方法,不一定要start()发起。
run()方法源码:
1 public void run() { 2 if (target != null) { 3 target.run(); 4 } 5 }
4.Thread对象
Thread类的对象其实也是一个java对象,只不过每一个Thread类的对象对应着一个线程(映射)。Thread类的对象就是提供给用户用于操作线程、获取线程的信息。真正的底层线程用户是看不到的了。
因此,当一个线程结束了,死掉了,对应的Thread的对象仍能调用,除了start( )方法外的所有方法(死亡的线程不能再次启动),如run( )、getName( )、getPriority()等等。
1 //简单起见,使用匿名内部类的方法来创建线程 2 Thread thread = new Thread(){ 3 @Override 4 public void run() { 5 System.out.println("Thread对象的run方法被执行了"); 6 } 7 }; 8 //线程启动 9 thread.start(); 10 11 //用循环去监听线程thread是否还活着,只有当线程thread已经结束了,才跳出循环 12 while(thread.isAlive()){} 13 //线程thread结束了,但仍能调用thread对象的大部分方法 14 System.out.println("线程"+thread.getName()+"的状态:"+thread.getState()+"---优先级:"+thread.getPriority()); 15 //调用run方法 16 thread.run(); 17 //当线程结束时,start方法不能调用,下面的方法将会抛出异常 18 thread.start();