持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
Java并发基础
为什么需要多线程
CPU、内存、I/O设备的速度是有极大的差异的,为了合理利用CPU的高性能,平衡三者的速度差异,
从而提高程序的计算效率。
线程的创建、启动与运行
java创建线程的四种方法
1、继承Thread类创建线程
2、实现Runnable接口创建线程
3、使用Callback和Future创建线程
4、使用线程池
-- 继承Thread类创建线程 --
public class MyThread extends Thread{//继承Thread类
public void run(){
//重写run方法
}
}
public class Main {
public static void main(String[] args){
new MyThread().start();//创建并启动线程
}
}
-- 实现Runnable接口创建线程 --
public class MyThread2 implements Runnable {//实现Runnable接口
public void run(){
//重写run方法
}
}
public class Main {
public static void main(String[] args){
//创建并启动线程
MyThread2 myThread=new MyThread2();
Thread thread=new Thread(myThread);
thread().start();
//或者 new Thread(new MyThread2()).start();
}
}
-- 使用Callable和Future创建线程 --
public static class MyThread3 implements Callable{
@Override
public Object call() throws Exception {
return 5;
}
}
public class Main {
public static void main(String[] args){
MyThread3 th=new MyThread3();
//也可以直接使用Lambda表达式创建Callable对象
//使用FutureTask类来包装Callable对象
FutureTask<Integer> future=new FutureTask<Integer>(
(Callable<Integer>)()->{
return 5;
}
);
new Thread(future,"有返回值的线程").start();//实质上还是以Callable对象来创建并启动线程
try{
System.out.println("子线程的返回值:"+future.get());//get()方法会阻塞,直到子线程执行结束才返回
}catch(Exception e){
ex.printStackTrace();
}
}
}
-- 使用线程池例如用Executor框架 --
java中提供了四种ThreadPool分别为
newCachedThreadPool()、newFixedThreadPool()、newScheduledThreadPool()、newSingleThreadExecutor()
线程属性
线程的属性包括线程的编号、名称、线程类别、优先级,如下表格
| 属性 | 属性类型及用途 | 只读属性 |
|---|---|---|
| 编号 (ID) | 类型:long。用于标识不同的线程。不同的线程有不同的编号 | 是 |
| 名称 (Name) | 类型:string。用于区分不同的线程。默认值与线程的编号有关,默认格式:Thread-线程编号 | 否 |
| 线程类别 (Daemon) | 类型:boolean。值为true表示对应的线程为守护线程,否则表示对应的线程为用户线程。该属性默认值与父线程的值相同 | 否 |
| 优先级 (Priority) | 类型:int。该属性本质上是给线程调度器的提示,用于表示应用程序希望那个线程能够优先得到运行。Java定义了1-10的10个优先级。默认值为5 | 否 |
线程的生命周期
线程共有5种生命周期分别为:
新建 (New)、就绪(Runnable)、运行(Running)、阻塞 (Blocked)和死亡 (Dead)5 种状态
多线程编程的优势和风险
优势
1、提高系统的吞吐率
2、提高响应性
3、充分利用多核处理器资源
4、最小化对系统资源的使用
5、简化程序的结构
缺点
1、线程安全问题
2、线程火星问题
3、上下文切换
4、可靠性