线程的基本解析

线程对象是能够产生线程的对象。好比在Java平台中Thread对象,Runnable对象。线程,是指正在执行的一个指点令序列。在java平台上是指从一个线程对象的start()开始,运行run方法体中的那一段相对独立的过程。相比于多进程,多线程的优点有:java

    (1)进程之间不能共享数据,线程能够;程序员

    (2)系统建立进程须要为该进程从新分配系统资源,故建立线程代价比较小;面试

    (3)Java语言内置了多线程功能支持,简化了java多线程编程。编程

1、建立线程和启动多线程

  (1)继承Thread类建立线程类ide

经过继承Thread类建立线程类的具体步骤和具体代码以下:性能

   • 定义一个继承Thread类的子类,并重写该类的run()方法;spa

   • 建立Thread子类的实例,即建立了线程对象;.net

   • 调用该线程对象的start()方法启动线程。线程

class SomeThead extends Thraad { public void run() { //所要重写的方法
 } } public static void main(String[] args){ SomeThread oneThread = new SomeThread(); 步骤3:启动线程: oneThread.start(); }

 

(2)实现Runnable接口建立线程类

经过实现Runnable接口建立线程类的具体步骤和具体代码以下:

   • 定义Runnable接口的实现类,并重写该接口的run()方法;

   • 建立Runnable实现类的实例,并以此实例做为Thread的target对象,即该Thread对象才是真正的线程对象。

class SomeRunnable implements Runnable { public void run() { //所要重写的方法 
 } } Runnable oneRunnable = new SomeRunnable(); Thread oneThread = new Thread(oneRunnable); oneThread.start();

以上的两种方法都可实现建立线程类

然而,本魔王一开始乍一看的时候感受大致上好像并无什么区别,但事实显然并无这么简单,试问一下,当使用Thread时候若有需求要求继承其余类的时候,是能够用extend继承父类的域,那万一要继承的不仅是一个父类呢,Thread毕竟只是一个类,不是接口,诶!!对了,这时候用Runnable就会方便不少,下面为你们总结的是Runnable与Thread的相关性。

 

****Runnable和Thread的区别和联系?****

1) Thread是一个类,Runnable是一个接口;

2) Thread类实现了Runnable接口,重写了run方法.

3) Runnable是一个接口,定义一个类实现接口的同时还能够继承其余的类 ; Runnable 支持多继承的写法;

4) Runable能够简单的实现数据的共享 ;Thread不太好实现;其实均可以实现

5) Runnable适合多个相同的程序代码的线程去处理同一个资源,避免Java中的单继承的限制,增长程序的健壮性,代码能够被多个线程共享,代码和数据独立。线程池只能放入实现Runnable 类线程,不能直接放入继承Thread的类.

 

在面试的时候,不少面试官都喜欢问一些关于线程状态的问题,可能很少问的特别细,但起码道理咱们得说的出来,下图是线程的生命周期,就挑几个常见的给你们解释的,其实有一些是我本身概括的,也有一些是网上dd下来的,懂的是什么道理,本身整理一套白话最好。

  • 新线程:
    •  用new关键字和Thread类或其子类创建一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有本身的内存空间,经过调用start方法进入就绪状态(runnable),它仅仅做为一个对象实例存在, JVM没有为其分配CPU时间片和其余线程运行资源;。

      注意:不能对已经启动的线程再次调用start()方法,不然会出现Java.lang.IllegalThreadStateException异常。

       

  • 就绪状态:
    • 在处于建立状态的线程中调用start方法将线程的状态转换为就绪状态(尽管是采用队列形式,事实上,把它称为可运行池而不是可运行队列。由于cpu的调度不必定是按照先进先出的顺序来调度的)。等待系统为其分配CPU。等待状态并非执行状态,当系统选定一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动做称之为“cpu调度”。一旦得到CPU,线程就进入运行状态并自动调用本身的run方法
    • 提示:若是但愿子线程调用start()方法后当即执行,可使用Thread.sleep()方式使主线程睡眠一伙儿,转去执行子线程。(sleep()方法在下面会解释)

       

  • 运行状态:
    • 处于运行状态的线程是最复杂的,有阻塞状态,就绪状态和死亡状态
    • 处于就绪状态的线程,若是得到了cpu的调度,就会从就绪状态变为运行状态,执行run()方法中的任务。若是该线程失去了cpu资源,就会又从运行状态变为就绪状态。从新等待系统分配资源。也能够对在运行状态的线程调用yield()方法,它就会让出cpu资源,再次变为就绪状态。(**当某个线程调用了yield()方法暂停以后,优先级与当前线程相同,或者优先级比当前线程更高的就绪状态的线程更有可能得到执行的机会,固然,只是有可能,由于咱们不可能精确的干涉cpu调度线程。)
  • 等待/阻塞:
    • 阻塞状态在这里我不便多说,由于我本身都还没看透(喷血),我只能理解的是当一个线程占用CPU运行时被其余线程或者语句剥夺或者说暂停了其了使用权,从而进入阻塞状态。
    • 在阻塞状态的线程不能进入就绪队列。只有当引发阻塞的缘由消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,从新到就绪队列中排队等待,被系统选中后从原来中止的位置开始继续运行。

 

 

 

Java提供了一些便捷的方法用于线程状态的控制,就举几个经常使用的例子,多了我也不会。具体以下:

一、线程睡眠——sleep

      若是咱们须要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则能够经过调用Thread的sleep方法。

注:

   (1)sleep是静态方法,最好不要用Thread的实例对象调用它,由于它睡眠的始终是当前正在运行的线程,而不是调用它的线程对象,它只对正在运行状态的线程对象有效。以下面的例子:

 1 package day7_3HomeWork;
 2 
 3 public class Thread_text {
 4 
 5     public static void main(String[] args) {
 6         Thread_input ti = new Thread_input();
 7         ti.start();
 8 
 9     }
10 }
11 class Thread_input extends Thread{
12     String[] str = {"我","我爱","我爱福","我爱福建","我爱福建工","我爱福建工程","我爱福建工程学","我爱福建工程学院"};
13     @Override
14     public void run() {
15         // TODO Auto-generated method stub
16         for(int i=0;i<str.length;i++)
17         {
18             System.out.println(str[i]);
19             try {
20                 sleep(2000);
21             } catch (InterruptedException e) {
22                 // TODO Auto-generated catch block
23                 e.printStackTrace();
24             }
25         }    
26     }
27 }

至关于只是暂停当前的进程运行,线程处于阻塞状态,在2000mills的睡眠时间结束的时候才能从新变回就绪状态,而就绪状态进入到运行状态,是由系统控制的,咱们不可能精准的去干涉它,因此若是调用Thread.sleep(1000)使得线程睡眠1秒,可能结果会大于1秒。下图是sleep的方法,须要传入的是一个long mills的参数,这是毫秒的单位。

(2)Java线程调度是Java多线程的核心,只有良好的调度,才能充分发挥系统的性能,提升程序的执行效率。可是无论程序员怎么编写调度,只能最大限度的影响线程执行的次序,而不能作到精准控制。

相关文章
相关标签/搜索