1、线程五种状态

  • 新建状态(new):创建线程Thread对象进入新建状态。
  • 就绪状态(runnable):调用start()方法,线程会进入就绪状态,如果得到CPU资源就会进入运行状态。
  • 运行状态(running) :就绪状态得到 CPU 资源就会转为运行状态,执行 run() 方法,当调用 yield() 时线程会让步,从运行状态转到就绪状态,但该过程可能是及其短暂的,如果当前线程拥有较高优先级,即使让步后还是会进入运行状态
  • 阻塞状态(blocked):会导致阻塞状态的方法主要有:sleep()、wait()、join()、等待获取锁、等待 I/O 等情况,在这些情况被处理后就会转为就绪状态,等待调度
  • 终止状态(dead):线程销毁

2、线程方法

(1)线程常用方法
  • start():使该线程开始执行,java虚拟机调用该线程的run()方法;
  • run():如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
  • setName(String name):改变线程名称,使之与参数 name 相同。
  • setPriority(int priority):更改线程的优先级。
  • setDaemon(boolean on):将该线程标记为守护线程或用户线程。
  • join(long millisec):等待该线程终止的时间最长为 millis 毫秒。把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程,比如在线程 B 中调用了线程 A 的 join() 方法,直到线程 A 执行完毕后才会继续执行线程 B。
  • interrupt():中断线程。该方法直接对线程调用。当被interrupt的线程正在sleep或wait时,会抛出InterruptedException异常。
  • isAlive():判断当前线程是否处于活动状态;
  • yield():调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的
  • sleep(long millisec):在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。
  • currentThread():可以返回代码段正在被哪个线程调用的信息。
  • wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
  • notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
  • notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;
  • 线程休眠和唤醒
public class MySleep {

	public static void main(String[] args) throws InterruptedException {
		sleepTest();
	}

	private static void sleepTest() throws InterruptedException {
		Thread thread = new Thread() {
			public void run() {
				System.out.println("线程 " + Thread.currentThread().getName() + "将要休眠5分钟。");
				try {
					Thread.sleep(5 * 60 * 1000);
				} catch (InterruptedException ex) {
					System.out.println("线程 " + Thread.currentThread().getName() + "休眠被中断。");
				}
				System.out.println("线程 " + Thread.currentThread().getName() + "休眠结束。");
			}
		};
		thread.setDaemon(true);
		thread.start();
		Thread.sleep(500);
		thread.interrupt();
	}
}
  • 线程同步等待
public class MyJoin{
    public static void main(String[] args) throws InterruptedException
    {
        joinTest();
    }
    
    private static void joinTest() throws InterruptedException
    {
        Thread thread = new Thread()
        {
            public void run()
            {
                try
                {
                    for(int i = 0; i < 10; i++)
                    {
                        System.out.println("线程在运行---"+i);
                        Thread.sleep(1000);
                    }
                }
                catch(InterruptedException ex)
                {
                    ex.printStackTrace();
                }
                
            }
        };
        thread.setDaemon(true);
        thread.start();
        thread.join();
        System.out.println("主线程正常结束。");
    }

}
  • 线程终止
public class MyInterrupt{
    public static void main(String[] args)
    {
        stopTest();
    }
    
    private static void stopTest()
    {
        Thread thread = new Thread()
        {
            public void run()
            {
                System.out.println("线程运行。");
                try {
                    Thread.sleep(1*60*1000);
                } catch (InterruptedException e) {
                    System.out.println("线程中断,结束线程");
                    return ;                    
                }
                System.out.println("线程正常结束");
                
            }
        };
        thread.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();
    }

}

总结

1、线程的sleep()方法和yield()方法有什么区别?

      (1)线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
      (2)sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
      (3)sleep()方法不考虑优先级,yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

2、线程的sleep()方法和wait()方法有什么区别?

      (1)sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。
      (2)wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。

3、守护线程与用户线程的区别?

      守护线程和用户线程的区别在于:守护线程依赖于创建它的线程,而用户线程则不依赖。举个简单的例子:如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。