0%

线程

进程与线程

进程

程序运行的基本单位,一个程序就是代表一个进程,进程与进程之间是相互独立的,它们是由 CPU 进行调度的(分配内存空间) ,由于它们是相互独立所以各自的资源不共享。一台电脑中可以运行多个程序,并且执行效率快,所以它是高效而且并发性的。在一个时间段中,可以执行多个进程(程序),一个进程是非常占内存空间的,对 CPU 的开销也是非常大的。

线程

程序流中最小的执行单位,一个程序中至少存在一个线程,线程占空间内存是非常少的,一个进程中多个线程资源是可以共享的。线程消耗的内存少执行效率高,同一时间段中可以执行多个线程,线程具有并发性的特点。(线程调度:(分时间)轮询调度和抢占式调度),资源共享;注意的是资源是否会丢失(安全)。

区别

  1. 一个程序至少有一个进程,一个进程至少有一个线程

  2. 线程的划分尺度小于进程,使得多线程程序的并发性高。

  3. 进程有独立的内存单元,而多个线程共享内存

  4. 线程必须依靠存在于应用程序中

  5. 多线程实在程序中多个部分同时执行,但是系统并没有把多个线程当场多个独立的应用,来实现进程的调度和管理资源分配。

  6. 线程开销小,不利于资源的管理和保护,进程正好相反。

  7. 线程数据共享

    线程的实现

    java 中一共有两种方式实现线程

    继承 Thread 类

    通过继承 java.lang.Thread 类来实现线程:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class MyThread extends Thread{
    @Override
    public void run(){
    .....
    }

    }
    public static void main(String[] args){
    MyThread mt = new MyThread();
    mt.start();
    }

    继承 Thread 类是之后要实现 run() 方法,线程启动之后是执行 run() 方法。之后调用 Thread 的 start 的方法就能开启线程( 同一对象不能调用同一 start() 方法)

    实现 Runnable 接口,并且 start()

    1. 内部类实现
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      new Thread(new Runnable(){

        @Override
        public void run() {
         int i=0;
          i++;
          System.out.println(i);
        }

      }).start();
      ```

      2. 另写一个类实现接口
      ```java
      class myRunnable implement Runnable{
      @Override
        public void run() {
         int i=0;
          i++;
          System.out.println(i);
        }
      }
      public static void main(String[] args){
      myRunnable mr = new myRunnable();
      Thread t1 = new Thread(mr);
      t1.start();
      }

生命周期

状态包括 出生状态,就绪状态,运行状态,等待状态,休眠状态,阻塞状态,死亡状态。

image
在用户 new 出来的时候为“出生状态”;此时当用户调用 start() 的时候处于“就绪状态”;当线程得到资源后进入“运行状态”;当运行时调用 wait() 方法时线程处于 “等待状态”,此时必须从其他线程调用 notify() 方法才能唤醒,notifyAll() 可以除了调用这个线程以外所有处于等待状态下的线程;当线程调用 sleep() 方法时会进入 “休眠状态”,结束后进入就绪;如果一个线程在运行状态下发出输入/输出(Sacnner)请求,该线程将进入阻塞状态,输入/输出结束时线程进入就绪 状态;当线程的 run() 方法执行完毕/异常/stop() 时线程进入“死亡状态”

线程常用方法

1. 线程的休眠( sleep )

静态方法,最后不要用 Thread 对象调用它,因为它睡眠的始终是当前正在运行的线程,不是调用它的线程对象,只对正在运行状态的线程对象有效。单位 ms 通常使得线程释放当前 cpu 执行权,苏醒后并不一定时运行状态,只能保证他进入就绪状态。

1
2
3
4
5
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}

2. 线程的加入(join)

不是静态方法,作用是当前线程等待这个调用 join() 方法对象的线程结束在继续执行 join() 下一句代码。

1
2
3
4
5
6
7
public static void main(String[] args) throws InterruptedException{
System.out.println("main start");
Thread t1= new Thread(new Worker("thread-1"));
t1.start();
t1.join();
System.out.println("main end");
}

如例子,main 线程要等到 t1 线程运行结束之后,才会输入“main end”。如果没有 join 那么变成并行,“main end”可能会被提前打印出来。

  1. 没有实现让其他线程并发执行,线程是顺序执行的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public static void main(String[] args) throws InterruptedException
    {
    System.out.println("main start");

    Thread t1 = new Thread(new Worker("thread-1"));
    Thread t2 = new Thread(new Worker("thread-2"));
    t1.start();
    //等待t1结束,这时候t2线程并未启动
    t1.join();

    //t1结束后,启动t2线程
    t2.start();
    //等待t2结束
    t2.join();

    System.out.println("main end");
    }
  2. 让t1、t2线程并行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class JoinTest
    {

    public static void main(String[] args) throws InterruptedException
    {
    System.out.println("main start");

    Thread t1 = new Thread(new Worker("thread-1"));
    Thread t2 = new Thread(new Worker("thread-2"));

    t1.start();
    t2.start();

    t1.join();
    t2.join();

    System.out.println("main end");
    }
    }

3. 线程的让步 yield()

yield()方法它也可以让当前正在执行的线程暂停,让出cpu资源给其他的线程。但是和sleep()方法不同的是,它不会进入到阻塞状态,而是进入到就绪状态。yield()方法只是让当前线程暂停一下,重新进入就绪的线程池中,cpu 调度重新调度,可能出现这样的情况:当某个线程调用yield()方法之后,调度器又将其调度出来重新进入到运行状态执行。

本文标题:线程

文章作者:志者

发布时间:2019年08月16日 - 15:48:00

最后更新:2019年08月28日 - 17:33:45

原始链接:http://witman1999.github.io/线程.html

许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------
copy