目录
概念
什么是进程?
举例说明,比如 windows 下的任务管理器中的进程列表,每个都是一个进程。
什么是线程?
线程是在进程中执行的,每个进程默认有一个主线程,当然,一个进程可以有多个线程。这多个线程之间的是并发执行的。
并发与并行
并发:简单点说,就是一个 CPU 切换着给多个线程执行任务。
并行:指一个 CPU 同时给多个线程都在执行任务。
创建线程的方式
继承 Thread 类
class MyThread extends Thread { @Override public void run() { // 子线程要执行的代码 System.out.println(getName() + " 我是子线程"); } }
通过 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(); }
通过线程池添加 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 中线程这块的基础知识,后续会更进一步的学习并记录。