多线程(九):线程相关知识点(创建方式,API,守护线程,状态转换)

来源:互联网 发布:八皇后问题循环算法 编辑:程序博客网 时间:2024/06/04 18:50

包括:

一. 线程创建方式(3种)
二. 线程常用API
三. 守护线程和非守护线程
四. 线程间的状态转换

一. 线程创建方式
        线程创建有3种方式:
1. 通过继承 Thread 类,重写父类的 run() 方法。如下代码:
public class ThreadTest {public static void main(String[] args) {Thread thread = new MyThread();thread.start();}}class MyThread extends Thread{@Overridepublic void run() {System.out.println("This is my Thread");}}

2. 实现 Runnable 接口,实现其 run() 方法。如下代码:
public class ThreadTest {public static void main(String[] args) {Thread thread = new Thread(new MyThread());thread.start();}}class MyThread implements Runnable{public void run() {System.out.println("This is my Thread");}}

3. 实现 Callable 接口,实现其 call() 方法。代码如下:
public class ThreadTest {public static void main(String[] args) {MyThread thread = new MyThread();try {System.out.println(thread.call());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class MyThread implements Callable<Integer>{@Overridepublic Integer call() throws Exception {return 2;}}

Ps:Callable 和 Runnable 的区别:
  1. Callable 接口可以有返回值,Runnable 接口 没有返回值。
  2. Callable 接口主要通过实现其 call() 方法, Runnable 接口主要实现其 run() 方法。

二. 线程常用API
2.1 currentThread() 取得当前线程:
public static native Thread currentThread();

2.2 yield() 函数:让当前运行的线程回到可运行的状态,以此运行具有相同优先级的其他线程获得运行机会。但是,在实际中无法保证 yield() 达到让步的目的,因为让步的线程可能会被再次选中。
public static native void yield();

2.3 sleep(long millis) 函数:休眠几秒;start() 函数:开始执行线程;run() 函数:具体的执行的业务逻辑方法。

Ps:sleep 方法和wait 方法的区别:
        sleep 方法不会释放对象锁。而 wait方法会释放对象锁。使用wait()方法之后,只有调用 notify() 或者 notifyAll()方法才能重新唤醒。 

2.4 interrupt() 方法:中断一个线程。会把线程状态设置为"中断"状态。注意:线程中断仅仅是置线程的中断状态,而不会停止线程。所以说,如果是普通使用interrupt() 方法,不加任何处理是无法中断一个线程的,如下代码:
public class ThreadTest {public static void main(String[] args) {Thread thread = new MyThread();thread.start();thread.interrupt();}}class MyThread extends Thread{public void run() {int i = 0;while(true){System.out.println(i++);}}}

        输出结果会一直打印下去。此时需要结合 sleep 和 interruptedException。
public class ThreadTest {public static void main(String[] args) {Thread thread = new MyThread();thread.start();thread.interrupt();}}class MyThread extends Thread{public void run() {try{int i = 0;while(true){System.out.println(i++);Thread.sleep(1);}} catch (InterruptedException ex){System.out.println("catch exception");}}}

        另外,还有一种方式 则是 通过 Thread.interrupted() 函数,能够告诉你线程是否发生了中断,并将清除中断标志位。所以程序不会两次告诉你线程发生了中断。所以可以如下方式:
public class ThreadTest {public static void main(String[] args) {Thread thread = new MyThread();thread.start();thread.interrupt();}}class MyThread extends Thread{public void run() {int i = 0;while(!Thread.interrupted()){System.out.println(i++);}}}

2.4 interrupted() 方法:得知是否中断了一个线程。返回当前的线程中断状态。注意:如果线程中断,该方法第一次调用的时候会返回true,但是返回之后马上就会清除中断标志位,下次再调用就会返回false。

2.5 isInterrupted() 方法:会返回当前的中断状态。但是不会像 interrupted() 方法一样清除中断标志位。

2.6 join() 方法:主要是让一个线程 B 加入到线程A 的尾部。在 A 执行完之前, B不能工作。另外, join 还有带超时限制的重载版本。例如, t.join(5000)。 例如如下代码:
public class ThreadTest {public static void main(String[] args) throws InterruptedException {Thread thread = new MyThread();thread.start();thread.join();for(int i = 0; i < 10; ++i){System.out.println("main:" + i);}}}class MyThread extends Thread{public void run() {for(int i = 0; i < 10; ++i){System.out.println("run:" + i);}}}

三. 守护线程和非守护线程
        Java中有两种线程,一种是守护线程,一种是非守护线程也就是用户线程。
        守护线程 主要是用来服务非守护线程的,如果没有用户线程在执行,那么守护线程也不会存在,因为它也没有服务的对象。守护线程可以通过 setDaemon(boolean on) 的方式来进行设置,true 为 守护线程模式,false 为用户模式。
        例如我们熟悉的垃圾回收线程就是一个典型的守护线程。

四. 线程间的状态转换
        线程状态分为几种,新建,运行,阻塞,等待,有限等待,中止。如下图:



那么从new到running,调用start()方法。

从Running到waitiing,调用wait()方法。

那么从Running到Blocked,遇到synchronized等需要同步的块。

从Running到Timed Waitiing,调用sleep()方法。

从Running到Terminated,则是run()方法执行结束。



参考:
  1. 用 interrupt() 中断 Java 线程:http://hapinwater.iteye.com/blog/310558
  2. java 线程 join 方法的使用:http://blog.sina.com.cn/s/blog_5c5bc9070100ytye.html




0 0