线程与进程
进程
-
是指一个内存中运行的应用程序,每个进程都有一个独立内存空间。
线程
-
是指进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程至少有一个线程;线程可以理解成是在进程基础上的进一步划分,一个进程启动之后,里面的若干执行路径可以划分成若干个线程。
线程的调度
分时调度
-
所有线程轮流使用CPU的使用权,如果线程的优先级相同,那么会随机选择一个(线程的随机性)
抢占式调度
-
CPU使用使用抢占式调度模式在多个线程间进行着高速的切换。其实多线程程序并不能提高程序的运行速度,但能够提高程序的运行效率,让CPU的使用率更高。
同步与异步
同步:排队执行,效率低但数据安全。
异步:同时执行,效率高数据不安全。
并发与并行
并发:两个或多个事件在同一时间段内发生。
并行:两个或多个事件在同一时刻发生(同时发生)。
Java中实现多线程
继承Therad类
public class MyThread extends Thread{ @Override public void run(){ //这里的代码就是一条新的执行路径 //提高thread对象的start()来启动任务 } }
public static void main(String[] args){ MyThread t=new MyThread(); t.start(); //执行run()方法 }
(子线程任务里调用的方法,都在子线程中运行)
实现Runnable接口
public class MyRunnable implements Runnable{ @Override public void run(){ //线程执行的任务 } }
public static void main(String[] args){ MyRunnable r=new MyRunnable(); //创建一个任务对象 Thread t=new Thread(); //创建一个线程,并为其分配一个任务 t.start(); //执行这个线程 }
实现Runnable接口与继承Therad类相比有如下优势:
-
通过创建任务,然后通过给线程进行分配来实现多线程,更适合多个线程同时执行相同任务的情况。
-
可以避免单继承所带来的局限性。(Java是单继承多实现)
-
任务与线程本身是分离的,提高程序的健壮性。
-
后续学习的线程池技术,接受Runnable类型的任务,不接受Therad类型的线程。
daemon线程(守护线程)与用户线程:
-
用户线程可以自己结束,而daemon线程只有当用户线程全部结束了才能结束。
获取线程的名称
-
Thread.currentThread().getName()
线程休眠
-
Thread.sleep(1000) //休眠一秒钟
线程不安全问题
-
解决方案1:同步代码块
格式:synchronized(锁对象){}
每个线程同用一个锁
-
解决方案2:同步方法
-
解决方案3:显示锁 Lock
锁:l.lock() 解锁:l.unlock()
线程死锁解决:在任何有可能导致锁产生的方法里,不要再调用另外一个可能会产生锁的方法。
多线程通信问题:生产者与消费者关系
生产者生成食物时,消费者等待,生产完食物之后:
this.notifyAll(); //唤醒消费者
this.wait(); //生产者等待
消费者消耗食物时,生产者等待,消耗完食物之后:
this.notifyAll(); //唤醒生产者
this.wait(); //消费者等待
线程的六种状态
-
NEW
尚未启动的线程处于此状态。
-
RUNNABLE
在Java虚拟机中执行的线程处于此状态。
-
BLOCKED
被阻塞等待监视器锁定的线程处于此状态。
-
WAITING
无限期等待另一个线程执行特定操作的线程处于此状态。
-
TIMED_WAITING
正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。
-
TERMINATED
已退出的线程处于此状态。
Callable接口
-
Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。
使用步骤:
1. 编写类实现Callable接口 , 实现call方法 class XXX implements Callable<T> { @Override public <T> call() throws Exception { return T; } } 2. 创建FutureTask对象 , 并传入第一步编写的Callable类对象 FutureTask<Integer> future = new FutureTask<>(callable); 3. 通过Thread,启动线程 new Thread(future).start()