多线程创建方式以及线程状态转换

Java多线程的实现方式(3种)

创建方式:继承Thread类,实现runnable接口,实现Callable接口

 

1、继承Thread类:

hread 是一个类。Thread本身就实现了Runnable接口

public class MyThread extends Thread { 

      public void run() { 

       System.out.println("MyThread.run()"); 

      } 

    } 

    MyThread myThread1 = new MyThread(); 

    myThread1.start();

   

2、实现Runnable接口:

Runnable 是一个接口,该接口中只包含了一个run()方法

public class MyThread immplements Runnable {

        public void run(){

            sysout.out.println("MyThread.run()");

        }

    }

    MyThread runThread = new MyThread();

    Thread runThread = new Thread(runThread,"");

    runThread.start();

   

3、实现Callable接口,通过FutureTask包装器创建Thread线程

/*

 *Callable接口实际上是属于Executor框架中的功能类,

 Callable接口与Runnable接口的功能类似,

 但提供了比Runnable更加强大的功能。

 *

 *Callable可以在任务结束的时候提供一个返回值,

  Runnable无法提供这个功能

 *Callable的call方法分可以抛出异常,

  而Runnable的run方法不能抛出异常。

 /

class Tickets<Object> implements Callable<Object> {

 

    //重写call方法

    @Override

    public Object call() throws Exception {

        // TODO Auto-generated method stub

        for (int i = 0; i < 5; i++) {

            System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);

        }

        return null;

    }

}

实现区别

 

1)、继承Thread类为单继承,实现Runnable方法为多实现,所以在灵活性上来说,使用实现Runnable方法更灵活;

2)、通过实现Runnable接口的方式可以实现多线程内的资源共享;

3)、增加代码的健壮性,代码可以被多个线程共享,代码和数据独立;

4)、线程池只能放实现Runnable或callable类的线程,不能直接放入继承Thread类的线程;

 

Runable接口和Thread类的区别主要包括以下几个方面

线程类继承自Thread则不能继承其他类(单继承)、而Runable接口可以

线程类继承自Thread相对于Runable来说,使用线程的方法更方便一些

实现Runnable接口的线程类的多个线程、可以更方便的访问同一个变量,而Thread类需要内部类来进行替换

 

Callable 和 Runnable接口的区别

Callable规定的方法是call(),而Runnable规定的方法是run().

Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

call()方法可抛出异常,而run()方法是不能抛出异常的。

运行Callable任务可拿到一个Future对象, Future表示异步计算的结果。

它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。

通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。

Callable是类似于Runnable的接口,

线程常用方法

start()

 

start():他的作用是启动一个新线程。start需要首先调用,start不能被重复调用,

run()

 

run(): run()就和普通的成员方法一样,可以被重复调用。

单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程!

yield()

 

yield()定义在Thread.java中,是Thread的静态方法

yield()的作用是让步。它能让当前正在执行的线程由“运行状态”进入到“就绪状态”,

从而让其它具有相同优先级的等待线程获取执行权;

但是,并不能保证在当前线程调用yield()之后,

其它具有相同优先级的线程就一定能获得执行权;

也有可能是当前线程又进入到“运行状态”继续运行!

sleep()

 

ssleep()定义在Thread.java中,是Thread的静态方法;

sleep方法的作用是让线程休眠指定时间,在时间到达时自动恢复线程的执行;

sleep方法不会释放线程锁;

在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。

join()

 

join() 定义在Thread.java中。

join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行

使用方法:

在Father线程中调用:

 sonThread.join();

则father线程会阻塞到son线程完成。

 join的原理是用wait做的,因此其行为类似wait。

interrupt()o

 

Thread中的stop()和suspend()方法,由于固有的不安全性,已经建议不再使用!

interrupt()的作用是中断当前线程。

 

终止处于“阻塞状态”的线程

当线程由于被调用了sleep(), wait(), join()等方法而进入阻塞状态;

若此时调用线程的interrupt()将线程的中断标记设为true。由于处于阻塞状态,中断标记会被清除,

同时产生一个InterruptedException异常。将InterruptedException放在适当的位置就能终止线程

 

终止处于“运行状态”的线程

interrupt()并不会终止处于“运行状态”的线程!它会将线程的中断标记设为true

isDaemon() setDaemon()

 

守护线程

Java 中有两种线程:用户线程和守护线程。可以通过isDaemon()方法来区别它们:

如果返回false,则说明该线程是“用户线程”;否则就是“守护线程”。

 

用户线程一般用户执行用户级任务,而守护线程也就是“后台线程”,一般用来执行后台任务。

需要注意的是:Java虚拟机在“用户线程”都结束后会后退出。

setPriority() getPriority()

 

线程优先级、来指导JVM层面优先来执行那个成程序,

但最终的执行顺序需要操作系统来指定

 

java 中的线程优先级的范围是1~10,

最小值是1、默认的优先级是5。最大值是10

“高优先级线程”会优先于“低优先级线程”执行。

线程状态及状态转换

线程状态(5种)

 

public enum State {

    NEW,新建状态 ->new  Thread  给线程分配内存空间

    RUNNABLE,执行状态 

    BLOCKED,阻塞状态

    WAITING,等待状态:wait()线程进入wait状态

    TIMED_WAITING,超时等待状态

    TERMINATED;终止状态,线程执行完成的状态

}

 

JDK源码解读

NEW:

   Thread state for a thread which has not yet started

RUNNABLE:

   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

BLOCKED:

   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 {Object.wait}

WAITING:

   Thread state for a waiting thread.

   A thread is in the waiting state due to calling one of the following methods:

   1、{Object.wait} with no timeout

   2、{Thread.join} with no timeout

   3、{LockSupport.park}

   A thread in the waiting state is waiting for another thread to perform a particular action

   For example, a thread that has called Object.wait()

   on an object is waiting for another thread to call

   Object.notify() or Object.notifyAll() on that object.

   A thread that has called Thread.join() is waiting for a specified thread to terminate.

TIMED_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:

   1、{Thread.sleep}

   2、{Object.wait} with timeout

   3、{Thread.join} with timeout  

   4、{LockSupport.parkNanos}

   5、{LockSupport.parkUntil}

TERMINATED:

   Thread state for a terminated thread.

   The thread has completed execution

  

新建状态(New)

用new语句创建的线程处于新建状态,此时它和其他Java对象一样,仅仅在堆区中被分配了内存。

就绪状态(Runnable)

当一个线程对象创建后,其他线程调用它的start()方法,该线程就进入就绪状态,

Java虚拟机会为它创建方法调用栈和程序计数器。处于这个状态的线程位于可运行池中,等待获得CPU的使用权。

运行状态(Running)

处于这个状态的线程占用CPU,执行程序代码。只有处于就绪状态的线程才有机会转到运行状态。

阻塞状态(Blocked)

阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,

Java虚拟机不会给线程分配CPU。直到线程重新进入就绪状态,它才有机会转到运行状态。

阻塞状态可分为以下3种:

1、位于对象等待池中的阻塞状态(Blocked in object’s wait pool):

当线程处于运行状态时,如果执行了某个对象的wait()方法,Java虚拟机就会把线程放到这个对象的等待池中,

 这涉及到“线程通信”的内容。

2、位于对象锁池中的阻塞状态(Blocked in object’s lock pool):当线程处于运行状态时,

试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他线程占用,

Java虚拟机就会把这个线程放到这个对象的锁池中,这涉及到“线程同步”的内容。

3、其他阻塞状态(Otherwise Blocked):当前线程执行了sleep()方法,

或者调用了其他线程的join()方法,或者发出了I/O请求时,就会进入这个状态。

死亡状态(Dead)

当线程退出run()方法时,就进入死亡状态,该线程结束生命周期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值