多线程-2.线程创建方式和Thread类
阅读原文时间:2023年07月09日阅读:1

线程的创建方式

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):表示该线程已经执行完毕。

  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();