线程

65 阅读4分钟

1. 并发,并行,线程,进程

并发:多件事情在同一时间段内发生
例如:一个人在10分钟内,一边喝水,一边看电视,一边吃饭,
并行:多件事情在同一时刻发生
例如:A和B同时(同时同分同秒)在工作。
进程:指一个应用程序在操作系统执行,例如:QQ,浏览器,微信等。
线程:一个进程的最小执行单元,一个进程最少有一个线程,可以有多个线程。
线程的调度方式
分时调度: 多个线程使用CPU的时间是相同的。
抢占式调度:多个线程抢占cpu,哪个线程抢到,哪个就运行。
一个cpu只能执行一个线程,当电脑上同时运行多个应用程序的时候,cpu的频繁的切换线程,在宏观角度看像是同时运行多个程序,但在微观上看是串行执行的。
如果是多个cpu,那么就能实现并行执行。

2. 创建线程

继承Thread类

i

继承Thread类,重写run方法,创建Therad子类示例,调用start方法。

public class OneThread  {
   public static void main(String[] args) {
       //3.创建一个Thread子类示例
       TwoThread twoThread = new TwoThread();
       //4.调用start方法
       twoThread.start();
       for (int i = 0; i < 20; i++) {
           System.out.println("one 主线程" + i);
       }
   }
}
// 1.创建Thread子类
class TwoThread extends Thread {
   //2. 重写run方法
   @Override
   public void run() {
       for (int i = 0; i < 20; i++) {
           System.out.println("Two 子线程" + i);
       }
   }
}

image.png 执行结果如上图,因为一个cpu在同一时刻只能执行一个线程,所以多个线程时哪个线程抢到资源会执行哪个线程。
如果是调用run方法,那么就不会创建新的线程,只有一个主线程。执行结果如下图。

image.png

实现Runnable

1.创建一个类实现Runnable接口
2.重写run方法
3.创建Runnable接口实现类的实例
4.用twoRunnable 作为target 创建一个Thread示例,
5.调用start方法
public class OneThread  {
    public static void main(String[] args) {
        //3.创建Runnable接口实现类的实例
        TwoRunnable twoRunnable = new TwoRunnable();
        //4.用twoRunnable 作为target 创建一个Thread示例,
        Thread thread = new Thread(twoRunnable);
        //5.调用start方法
        thread.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("one 主线程" + i);
        }
    }
}
//1.创建一个类实现Runnable接口
class TwoRunnable implements  Runnable{
    //2. 重写run方法
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Runnable 子线程" + i);
        }
    }
}

image.png Runnable接口可以用来实现:多个相同的程序代码线程共享同一个资源。
如下: 创建一个 c 的共享资源,创建两个线程,去对c修改。

public class OneThread  {
    public static void main(String[] args) {
        TwoRunnable twoRunnable = new TwoRunnable();
        Thread thread = new Thread(twoRunnable,"1");
        Thread thread2 = new Thread(twoRunnable,"2");
        thread.start();
        thread2.start();
    }
}
class TwoRunnable implements  Runnable{
    private int c = 8;
    @Override
    public void run() {
        for (int i = 0; i < 4; i++) {
            System.out.println( "第 "+Thread.currentThread().getName() + "个线程" + c--);
        }
    }
}

image.png

当然继承Thread 也可以,声明变量c:

private static int c = 8;

继承Thread和实现Runnable接口有什么不一样:

  1. java 是单继承,如果继承了Thread就没办法继承其他的类,如果是实现Runnale接口那么就可以继承其他类。
  2. Runnable 可以更便捷的共享同一个资源。
  3. 增强代码的健壮性,同一个代码可以被多个线程共享,实现代码和线程的解耦。

3. 线程常用方法

线程的优先级

public final void setPriority(int newPriority)
/**
  * The minimum priority that a thread can have.
  */
 public final static int MIN_PRIORITY = 1;

/**
  * The default priority that is assigned to a thread.
  */
 public final static int NORM_PRIORITY = 5;

 /**
  * The maximum priority that a thread can have.
  */
 public final static int MAX_PRIORITY = 10;

可以通过setPriority()设置线程的优先级,该参数是1到10,最大是10 最小是1。优先级:不能决定线程一定会先执行,只能反映线程紧急程度。

休眠

可以指定线程睡眠的毫秒数: Thread.sleep(1000);

public static native void sleep(long millis) throws InterruptedException;

设置让步

Thread.yield();

暂停当前正在执行的线程对象(放弃当前占有的cpu资源),回到可运行状态,重新去竞争cpu资源,所以在实际中可能达不到 yield() 让步的目的。

合并

public final void join() throws InterruptedException {
    join(0);
}
thread2.join();

当主线程执行的时候,子线程调用join()方法,这时候主线程等待 子线程执行完再执行。

守护线程

主线程结束,守护线程也自动结束,垃圾回收器线程属于守护线程。

thread2.setDaemon(true); // 设置守护线程

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情