Java_线程
什么是进程?
进程是指可执行程序并存放在计算机存储器的一个指令序列,它是一个动态的执行过程;
多任务可以同时进行
什么是线程?
线程是比进程更小的运行单位,线程相当于一个子程序;
cpu通过时间片轮转的方式来达到多任务同时运行的效果
线程的创建:
一 : 创建Thread类的子类
二 : 创建实现Runnable接口的类
1、代码复杂程度: 继承Thread方式简单 实现Runnable接口的方式比较复杂 2、实现原理: 继承方式:调用start方法,调用start0方法,start0是本地方法(native),由虚拟机 实现,是C语言实现的方法,所以在java中看不到代码。本地方法start0返回来调用java中 的run方法,run方法已经在子类中重写过了,所以最终运行的是子类重写了的run方法 实现方式:构造方法中,将Runnable的实现类对象传入构造方法中,经过一路init方法的 传递,最终,用于给Thread类型中的某个成员变量(target)赋值;调用对象的start方 法,最终也是返回来调用Thread类中的run方法,判断当前的成员变量target是否为null, 如果不为null,就调用target的run方法,而这个run方法我们已经重写过了,最终运行的是 我们重写过的run方法。 3、设计:java中只支持单继承、不支持多继承 继承方式:某个类继承了Thread类,那么就无法继承其他业务中需要的类型,就限制了 我们的设计。所以扩展性较差。 实现方式:某个类通过实现Runnable的方式完成了多线程的设计,仍然可以继承当前业 务中的其他类型,扩展性较强。 4、灵活性: 继承方式:将线程对象和任务内容绑定在了一起,耦合性较强、灵活性较差 实现方式:将线程对象和任务对象分离,耦合性就降低,灵活性增强:同一个任务可以 被多个线程对象执行,某个线程对象也可以执行其他的任务对象。并且将来还可以将任务类 对象,提交到线程池中运行;任务类对象可以被不同线程运行,方便进行线程之间的数据交 互 |
有返回值的线程创建方式 实现Callable接口
1、步骤:
(1)定义一个类实现Callable接口
(2)在实现类中重写call()方法
(3)创建实现类的对象
(4)创建Future接口的实现类FutureTask对象,把实现类对象作为构造方法的参数
(5)创建Thread类的对象,把FutureTask对象作为构造方法的参数
(6)启动线程
(7)FutureTask对象再调用get方法,就可以获取线程结束之后的结果
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo03_ImplCallable {
/*
* 1、Runnable没有返回值,callable有
* 2、Runnable不能抛异常,但callable可以
*
* */
public static void main(String[] args) throws ExecutionException, InterruptedException {
//3.创建Callable接口的实现类对象
CallImpl c = new CallImpl();
//4.将Callable的实现类对象,包装成一个任务对象FutureTask
FutureTask<String> task = new FutureTask<>(c);
//5.创建线程对象,将任务对象添加到线程中
Thread t = new Thread(task);
//6.启动线程
t.start();
//7.可以使用FutureTask的get方法,获取传入的Callable对象的call方法返回的结果
String s = task.get();
System.out.println(s);
}
}
//1.自定义类型,实现Callable接口
class CallImpl implements Callable<String> {
//2.实现call方法
@Override
public String call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println("嫁给我吧!");
if(i == 11) {
throw new Exception();
}
}
return "滚";
}
}
线程的状态:
1.新建(New)
2.可运行(Runnable)
3.运行时(Running)
4.阻塞(Blocked)
5.终止(Dead)
线程的生命周期
线程的优先级:
Java为线程一共了10个优先级;数字越大,优先级越高
优先级可以用1-10的整数表示,超出范围会抛出异常;
main()主线程的默认优先级为5;
常量优先级:MAX_PRIORITY:最高优先级10
MIN_PRIORITY:最高优先级0
NORM_PRIORITY:默认优先级5
注意:线程优先级的设置受操作系统环境的影响,不能完全保证优先级高的线程就一定优先运行;
线程同步
各个线程通过竞争CPU时间而获得运行机会;
各线程占用CPU的时间是不可预测的;
一个线程在什么时候会被暂停也是不可预测的;
使用同步关键字synchronized将对象锁定,只允许一个线程对当前对象进行操作
同步方法:public synchronized void add(){}
同步语句块:synchronized(obj){} obj是指要锁定的对象,如 synchronized(this){}
线程间通信
生产者和消费者问题:
定义一个boolean变量,把当前对象看作一个容器,为true时,表示容器中有产品,不需要生产(线程等待),可以消费;为false时,需要生产,才能消费(线程等待).
激活wait()线程的方法:notify()唤醒等待的某一个线程(随机).
notifyAll()唤醒所有线程.