Java核心类库篇7——多线程
Java核心类库篇7——多线程
1、程序、进程和线程
- 程序 - 数据结构 + 算法,主要指存放在硬盘上的可执行文件
- 进程 - 主要指运行在内存中的可执行文件
- 线程就是进程内部的程序流
操作系统内部支持多 进程的,而每个进程的内部又是支持多线程的
2、线程的创建
方法声明 | 功能介绍 |
---|---|
public Thread() | 使用无参的方式构造对象 |
public Thread(String name) | 根据参数指定的名称来构造对象 |
public Thread(Runnable target) | 根据参数指定的引用来构造对象,其中Runnable是个接口类型 |
public Thread(Runnable target, String name) | 根据参数指定引用和名称来构造对象 |
public void run() | 若使用Runnable引用构造了线程对象,调用该方法时最终调 用接口中的版本 若没有使用Runnable引用构造线程对象,调用该方法时则啥也不做 |
public void start() | 用于启动线程,Java虚拟机会自动调用该线程的run方法 |
public long getId() | 获取调用对象所表示线程的编号 |
public String getName() | 获取调用对象所表示线程的名称 |
public void setName(String name) | 设置/修改线程的名称为参数指定的数值 |
public static Thread currentThread() | 获取当前正在执行线程的引用 |
2.1、继承Thread类
- 优点:实现起来简单,而且要获取当前线程,无需调用Thread.currentThread()方法,直接使用this即可获取当前线程
- 缺点:线程类已经继承Thread类了,就不能再继承其他类,多个线程不能共享同一份资源
public class MyThread extends Thread {@Overridepublic void run() {for (int i = 0; i < 50; i++) {System.out.println(this.getName()+"----------------"+i);}}
}
public class Test {public static void main(String[] args) {new MyThread().start();for (int i = 0; i < 50; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}}
}
注:直接调用run方法如同调用类成员方法一样
2.2、实现Runnable接口
- 优点:线程类只是实现了接口,还可以继承其他类,多个线程可以使用同一个target对象,适合多个线程处理同一份资源的情况
- 缺点:通过这种方式实现多线程,相较于第一类方式,编程较复杂,要访问当前线程,必须调用Thread.currentThread()方法
public class MyRunable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 50; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}}
}
public class Test {public static void main(String[] args) {new Thread(new MyRunable()).start();for (int i = 0; i < 50; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}}
}
2.3、Callable和FutureTask
- 优点:线程类只是实现了接口,还可以继承其他类,多个线程可以使用同一个target对象,适合多个线程处理同一份资源的情况
- 缺点:通过这种方式实现多线程,相较于第一类方式,编程较复杂,要访问当前线程,必须调用Thread.currentThread()方法
public class Test {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {for (int i = 0; i < 50; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}return 100;}});new Thread(futureTask, "ruoye").start();for (int i = 0; i < 50; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}System.out.println(futureTask.get());}
}
lambda表达式
public class Test {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<Integer> futureTask = new FutureTask<>((Callable<Integer>) () -> {System.out.println("hello world!");return 100;});new Thread(futureTask, "ruoye").start();for (int i = 0; i < 50; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}System.out.println(futureTask.get());}
}
3、线程优先级及线程让步
方法声明 | 功能介绍 |
---|---|
public static void yield() | 当前线程让出处理器(离开Running状态),使当前线程进入Runnable 状态等待 |
public static void sleep(times) | 使当前线程从 Running 放弃处理器进入Block状态, 休眠times毫秒 |
public int getPriority() | 获取线程的优先级 |
public void setPriority(int newPriority) | 修改线程的优先级,优先级越高的线程不一定先执行,但该线程获取到时间片的机会会更多 一些 |
public void join() | 等待该线程终止 |
public void join(long millis) | 等待参数指定的毫秒数 |
public boolean isDaemon() | 用于判断是否为守护线程 |
public void setDaemon(boolean on) | 用于设置线程为守护线程 |
sleep
public class Test {public static void main(String[] args) {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");while (true){System.out.println(simpleDateFormat.format(new Date()));try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
setPriority线程优先级
public class Test {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println(Thread.currentThread().getName()+"优先级-----"+Thread.currentThread().getPriority());for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+"-----"+i);}});thread.setName("ruoye");thread.setPriority(Thread.MAX_PRIORITY);thread.start();for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+"-----"+i);}}
}
线程等待
public class Test {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-----"+i);}});thread.setName("ruoye");thread.start();
// thread.join();
// System.out.println("终于等到你");thread.join(5000);System.out.println("没有等到你");}
}
守护线程
public class Test {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-----"+i);}});thread.setName("ruoye");thread.setDaemon(true);thread.start();Thread.sleep(5000);System.out.println("没有等到你");}
}
4、线程同步
4.1、多线程出现的问题
public class Account implements Runnable {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic void run() {System.out.println("进到门口");System.out.println("开始取钞");if (this.money>200){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}this.money-=200;System.out.println("取款成功");}}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';}
}
public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1000);Thread thread = new Thread(account);Thread thread1 = new Thread(account);thread.start();thread1.start();thread.join();thread1.join();System.out.println(account.getMoney());}
}
4.2、synchronized同步锁
4.2.1、synchronized代码块
下面所示为锁class,锁Account对象里的成员变量(对象)也可,但请时刻记住,多个Account为对象里的成员变量(对象)多个对象,那么就拥有了多把锁,此时应当用static修饰
休眠在同步代码块内不会让出cpu
public class Account implements Runnable {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic void run() {System.out.println("进到门口");synchronized (Account.class){System.out.println("开始取钞");if (this.money>200){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}this.money-=200;System.out.println("取款成功");}}}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';}
}
public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1000);Thread thread = new Thread(account);Thread thread1 = new Thread(account);thread.start();thread1.start();thread.join();thread1.join();System.out.println(account.getMoney());}
}
4.2.2、synchronized方法
当synchronized位于成员方法上等价于synchronized (this)
当当synchronized位于成员方法上等价于synchronized (类对象)
public class Account implements Runnable {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic synchronized void run() {System.out.println("进到门口");System.out.println("开始取钞");if (this.money>200){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}this.money-=200;System.out.println("取款成功");}}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';}
}
public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1000);Thread thread = new Thread(account);Thread thread1 = new Thread(account);thread.start();thread1.start();thread.join();thread1.join();System.out.println(account.getMoney());}
}
4.3、死锁问题
尽量减少同步的资源,减少同步代码块的嵌套结构的使用
线程一执行的代码
public void run(){synchronized(a){ //持有对象锁a,等待对象锁b synchronized(b){ //编写锁定的代码; }}
}
线程二执行的代码
public void run(){synchronized(b){ //持有对象锁a,等待对象锁b synchronized(a){ //编写锁定的代码; }}
}
4.4、Lock锁
- Lock是显式锁,需要手动实现开启和关闭操作,而synchronized是隐式锁,执行锁定代码后自动释放
- Lock只有同步代码块方式的锁,而synchronized有同步代码块方式和同步方法两种锁
- 使用Lock锁方式时,Java虚拟机将花费较少的时间来调度线程,因此性能更好
public class Account implements Runnable {private int money;private static Lock lock=new ReentrantLock();public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic void run() {lock.lock();System.out.println("进到门口");System.out.println("开始取钞");if (this.money>200){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}this.money-=200;System.out.println("取款成功");}lock.unlock();}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';}
}
public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1000);Thread thread = new Thread(account);Thread thread1 = new Thread(account);thread.start();thread1.start();thread.join();thread1.join();System.out.println(account.getMoney());}
}
5、线程通信
5.1、线程通信
不能锁class
public class Account implements Runnable {private int a;public Account(int a) {this.a = a;}@Overridepublic void run() {while (true){synchronized (this) {if (a<100){System.out.println(Thread.currentThread().getName()+"========"+a);a++;notify();try {wait();} catch (InterruptedException e) {e.printStackTrace();}}else{break;}}}}
}
public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1);Thread ruoye = new Thread(account, "ruoye");Thread yoya = new Thread(account, "yoya");ruoye.start();yoya.start();}
}
5.2、生产者消费者问题
- 线程间的通信共享数据一定要有同步代码块synchronized
- 一定要有wait和notify,而且二者一定是成对出现
- 生产者和消费者的线程实现一定是在while(true)里面
public class Mother implements Runnable {private Account account;public Mother(Account account) {this.account = account;}@Overridepublic void run() {while (true){try {account.produce();Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
public class Ming implements Runnable {private Account account;public Ming(Account account) {this.account = account;}@Overridepublic void run() {while (true){try {account.consumer();Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
public class Account {private int a;public Account(int a) {this.a = a;}public int getA() {return a;}public void setA(int a) {this.a = a;}public synchronized void produce() throws InterruptedException {notify();if (a<2000){a+=100;System.out.println("妈妈给小明存了100元");}else{wait();}}public synchronized void consumer() throws InterruptedException {notify();if (a>75){a-=75;System.out.println("小明花了75元");}else{wait();}}
}
public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(0);new Thread(new Mother(account)).start();new Thread(new Ming(account)).start();}
}
Java核心类库篇7——多线程相关推荐
- Java核心类库篇8——网络编程
Java核心类库篇8--网络编程 1.七层网络模型 OSI(Open System Interconnect),即开放式系统互联,是ISO(国际标准化组织)组织在1985 年研究的网络互连模型. 当发 ...
- Java核心类库篇6——IO
Java核心类库篇6--IO 1.File 1.1.构造方法 方法声明 功能介绍 public File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 ...
- Java核心类库篇5——异常
Java核心类库篇5--异常 java.lang.Throwable类是Java语言中错误(Error)和异常(Exception)的超类 其中Error类主要用于描述Java虚拟机无法解决的严重错误 ...
- Java核心类库篇4——集合
Java核心类库篇4--集合 1.集合的意义 记录单个数据内容时,则声明一个变量 记录多个类型相同的数据内容时,声明一个一维数组 记录多个类型不同的数据内容时,则创建一个对象 记录多个类型相同的对象数 ...
- Java核心类库篇3——util
Java核心类库篇3--util 1.Date 用于描述特定的瞬间,也就是年月日时分秒,可以精确到毫秒 1.1.构造方法 方法声明 功能介绍 public Date() 获取当前时间表示的date对象 ...
- Java核心类库篇2——lang
Java核心类库篇2--lang 1.Object 该类是所有类的父类,每个类都使用它作为超类,没有任何属性 方法声明 功能介绍 Object() 使用无参方式构造对象 boolean equals( ...
- Java核心类库篇1——简介
Java核心类库篇1--简介 1.核心类库 包名 主要功能 java.applet 提供了创建applet需要的所有类 java.awt.* 提供了创建用户界面以及绘制和管理图形.图像的类 java. ...
- Java核心类库之(多线程:实现多线程、线程同步)
目录 1 多线程 1.1 进程 1.2 线程 1.3 多线程的实现方式 1.3.1 方式1:继承Tread类 1.3.2 方式2:实现Runnable接口 1.3.3 方式3:实现Callable接口 ...
- 第四章Java核心类库_多线程
第四章第五节Java核心类库_多线程 多线程 一.线程与进程 1.线程与进程 2.线程调度 二.同步与异步&并发与并行 1. 同步与异步 2. 并发与并行 三.继承Thread 1.代码块 2 ...
最新文章
- Python机器学习:训练Tesseract
- SAP HANA中的存储过程(sql procedure)
- ae saber插件_【AE插件】 用于做动画制作/设计的五个免费插件 非常好用
- 主从mysql能过滤指定dml吗_MyCat教程二:mysql主从复制实现 - HG-93
- javaweb学习总结(九):通过Servlet生成验证码图片
- java dao 单元测试_Spring Service、Dao进行Junit单元测试
- (1)Linux进程调度
- totolink服务器未响应,TOTOLINK路由器设置后无法上网问题的解决方法
- Java开发工程师,每个阶段需要掌握什么重点?
- 谈表单的设计 (一) 合理对表单进行布局
- php 刷新腾讯云cdn
- Grubbs准则建模与分析 C与Matlab实现
- 基于系统的软件测试报告,软件系统测试报告模板.doc
- 爬网易云音乐动态的坑
- 4173: 数学 欧拉函数 思路题
- 用Qt实现Q-M算法化简逻辑表达式及Qt项目打包发布方法
- Spanning-tree guard features配置案例
- 【读书笔记】组合计数中的行列式方法
- Java自定义变换产生摘要数据
- linux 常见服务
热门文章
- stl vector 函数_vector :: back()函数以及C ++ STL中的示例
- 客户端通过网口启动可过去的ip_西安交通大学16年3月课程考试《网络组网技术综合训练》作业考核试题...
- python mpi开销_GitHub - hustpython/MPIK-Means
- ruby hash方法_Hash.fetch()方法以及Ruby中的示例
- ruby array_Array.select! Ruby中的示例方法
- 程序员进阶之路—如何独当一面
- Python:通过SNMP协议获取H3C、华为交换机的VLAN信息及ARP地址表
- 十四、PyCharm开发Python利用WMI修改电脑IP、DNS
- QT5快速转换路径(/斜杠与\反斜杠转换)
- POJ 1804 Brainman (归并排序 -- 求逆序对数)