JavaSE 之旅09——线程

目录

概念

什么是进程?

举例说明,比如 windows 下的任务管理器中的进程列表,每个都是一个进程。

什么是线程?

线程是在进程中执行的,每个进程默认有一个主线程,当然,一个进程可以有多个线程。这多个线程之间的是并发执行的。

并发与并行

并发:简单点说,就是一个 CPU 切换着给多个线程执行任务。

并行:指一个 CPU 同时给多个线程都在执行任务。


创建线程的方式

  1. 继承 Thread 类

    class MyThread extends Thread {
    
    @Override
    public void run() {
        // 子线程要执行的代码
        System.out.println(getName() + " 我是子线程");
    }
    }
  2. 通过 Thread 构造接受一个 Runnable 接口的示例

    class MyRunnable implements Runnable {
    
    @Override
    public void run() {
        // 子线程要执行的代码
        System.out.println(Thread.currentThread().getName() + " Runnable子线程");
    }
    
    }
    
    public static void main(String[] args) {
       new Thread(new MyRunnable()).start();
    }
  3. 通过线程池添加 Callable 对象(不推荐使用

    /**
    * 这种方式不推荐使用 会抛出异常
    * 
    * @author codexiaosheng
    *
    */
    class MyCallable implements Callable<Integer> {
    
    int num;
    
    public MyCallable(int num) {
        super();
        this.num = num;
    }
    
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= num; i++) {
            sum += i;
        }
        return sum;
    }
    }
    
    // main() 方法
    ExecutorService executorService = Executors.newFixedThreadPool(1);
    Future<Integer> future = executorService.submit(new MyCallable(100));
    executorService.shutdown();
    Integer sum = future.get();
    System.out.println(sum);

优缺点对比

第一种方式适合我们要操作的类没有继承其他类(因为 java 是单继承的);第二种方式则没有此限制,java 可以多实现,但是第二种方式相比于第一种方式有个缺点就是,需要创建线程对象然后通过构造参数的方式传入接口实例。

源码角度分析

继承 Thread 类的方式,其实是父类的中有 start() 方法,这个方法具体是如何调用 run() 方法的,从源码上是看不到的。而实现接口的方式,执行流程是这样的,构造方法传入一个 Runnable 接口实例,而在 Thread 类中定义了一个 Runnable 类型的成员变量,构造方法传入的 Runnable 实例最后赋值给了这个成员变量,在 Thread 类中重写了 run() 方法,在这个方法中调用了 Runnable 接口中的抽象方法。


线程的表现形式

休眠线程

sleep(long millis) :让当前线程睡眠多少毫秒。

守护线程

setDeamon(boolean on):设置当前线程是否为守护线程。

守护线程的特点:等待被守护的线程执行完。执行完之后,如果守护线程也有自己的任务,那么可能会执行也可能不执行(根据守护线程的任务情况和代码执行速度而定)。

加入线程

join():在当前线程中把别的线程给加进来,加进来之后可能是加进来的线程执行完自己的任务,当前线程再执行自己的任务,也有可能是两个线程交替执行。

该方法还有一个重载 join(毫秒值):被加入线程在指定时间后死亡。

优先级

setPriority():设置线程的优先级。优先级在 1~10 之间,默认是5.


同步代码块

java 中某段代码希望在 CPU 执行的时候不要被打断(去执行其他任务),等待执行完成之后再执行其他任务。这段在执行时不希望被打断的代码片段就是同步代码块。

synchronized:关键词表示 java 中的锁机制。

  • 同步代码块

    锁对象要是同一个。

  • 非静态同步方法

    所对象是 this.

  • 静态同步方法

    所对象是该类的字节码对象。


面试题:sleep() 和 wait() 的区别

  • sleep() 方法需要传入参数,在指定的时间内不释放锁(在同步函数或者同步代码块中),到时间后自动醒来。
  • wait() 方法可以传入参数也可以不传入参数,不传参数表示调用即处于等待状态,等待过程中释放锁(在同步函数或者同步代码块中);传入参数表示在给定的时间后开始等待。


总结

关于 java 中线程这块的基础知识,后续会更进一步的学习并记录。


发布了68 篇原创文章 · 获赞 210 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/wufeng55/article/details/81408999
今日推荐