Thread基础

记录Java Thread的基础点。
线程的实现 线程的定义有两种方式
  • 继承Thread类
  • 实现Runnable接口
线程的启动 无论是继承Thread类还是实现Runnable接口,线程的启动方式都是:
Thread thread = new Thread(); thread.start(); // 或者 Thread runnable = new Thread(new Runnable()); runnable.start();

run() 线程实际运行调用的是run()方法。
  • 其中Thread类中的run() 实际是调用传入Runnable对象的run()方法
@Override public void run() { if (target != null) { target.run(); } }

线程状态
NEW, // 新建,创建后尚未启动的线程处于这种状态RUNNABLE, // 运行 // 处于这种状态的线程有可能正在执行也有可能正在等待CPU分配执行时间BLOCKED, // 阻塞WAITING, // 无限期等待 // 处于这种状态CPU不会分配执行时间 // 需要其他线程唤醒TIMED_WAITING, // 限期等待 // 处于这种状态CPU不会分配执行时间 // 不需要其他线程唤醒,在一定时间之后会由系统自动唤醒TERMINATED; // 结束,线程已经结束执行

线程状态转换关系图:

Thread基础
文章图片
java-thread-status.jpg 线程的属性和方法 设置优先级
public final void setPriority(int newPriority)

每个类都有自己的优先级,一般property用1-10的整数表示,默认优先级是5,优先级最高是10;优先级高的线程并不一定比优先级低的线程执行的机会高,只是执行的机率高;默认一个线程的优先级和创建他的线程优先级相同。
sleep
public static native void sleep(long millis) throws InterruptedException; public static void sleep(long millis, int nanos) throws InterruptedException

可以使用TimeUnit的sleep方法
TimeUnit.MILLISECONDS.sleep(500L); // 内部实现还是调用Thread.sleep()实现的,源码如下 public void sleep(long timeout) throws InterruptedException { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); Thread.sleep(ms, ns); } }

当前线程睡眠/millis的时间(millis指定睡眠时间是其最小的不执行时间,因为sleep(millis)休眠到达后,无法保证会被JVM立即调度);sleep()是一个静态方法(static method) ,所以他不会停止其他的线程也处于休眠状态;线程sleep()时不会失去拥有的对象锁。作用:保持对象锁,让出CPU,调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留一定的时间给其他线程执行的机会;
yield
public static native void yield();

让出CPU的使用权,给其他线程执行机会、让同等优先权的线程运行(但并不保证当前线程会被JVM再次调度、使该线程重新进入Running状态),如果没有同等优先权的线程,那么yield()方法将不会起作用。
它仅能是一个线程从运行状态转换到可运行状态,而不是等待或阻塞状态。
join
public final void join() throws InterruptedExceptionpublic final synchronized void join(long mills) throws InterruptedExceptionpublic final synchronized void join(long millis, int nanos) throws InterruptedException

使用该方法的线程会在此之间执行完毕后再往下继续执行。
特殊的线程方法 object.wait()
// 存在对象 Object obj ; // 使用 synchronized(obj){ obj.wait(); // 无限等待 obj.wait(1000L); // 设定等待超时时间(有限等待) }

当一个线程执行到wait()方法时,他就进入到一个和该对象相关的等待池(Waiting Pool)中,同时失去了对象的机锁—暂时的,wait后还要返还对象锁。当前线程必须拥有当前对象的锁,如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常,所以wait()必须在synchronized 代码块中调用。
object.notify()/notifyAll()
【Thread基础】唤醒在当前对象等待池中等待的第一个线程/所有线程。notify()/notifyAll()也必须拥有相同对象锁,否则也会抛出IllegalMonitorStateException异常。

    推荐阅读