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——多线程相关推荐

  1. Java核心类库篇8——网络编程

    Java核心类库篇8--网络编程 1.七层网络模型 OSI(Open System Interconnect),即开放式系统互联,是ISO(国际标准化组织)组织在1985 年研究的网络互连模型. 当发 ...

  2. Java核心类库篇6——IO

    Java核心类库篇6--IO 1.File 1.1.构造方法 方法声明 功能介绍 public File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 ...

  3. Java核心类库篇5——异常

    Java核心类库篇5--异常 java.lang.Throwable类是Java语言中错误(Error)和异常(Exception)的超类 其中Error类主要用于描述Java虚拟机无法解决的严重错误 ...

  4. Java核心类库篇4——集合

    Java核心类库篇4--集合 1.集合的意义 记录单个数据内容时,则声明一个变量 记录多个类型相同的数据内容时,声明一个一维数组 记录多个类型不同的数据内容时,则创建一个对象 记录多个类型相同的对象数 ...

  5. Java核心类库篇3——util

    Java核心类库篇3--util 1.Date 用于描述特定的瞬间,也就是年月日时分秒,可以精确到毫秒 1.1.构造方法 方法声明 功能介绍 public Date() 获取当前时间表示的date对象 ...

  6. Java核心类库篇2——lang

    Java核心类库篇2--lang 1.Object 该类是所有类的父类,每个类都使用它作为超类,没有任何属性 方法声明 功能介绍 Object() 使用无参方式构造对象 boolean equals( ...

  7. Java核心类库篇1——简介

    Java核心类库篇1--简介 1.核心类库 包名 主要功能 java.applet 提供了创建applet需要的所有类 java.awt.* 提供了创建用户界面以及绘制和管理图形.图像的类 java. ...

  8. Java核心类库之(多线程:实现多线程、线程同步)

    目录 1 多线程 1.1 进程 1.2 线程 1.3 多线程的实现方式 1.3.1 方式1:继承Tread类 1.3.2 方式2:实现Runnable接口 1.3.3 方式3:实现Callable接口 ...

  9. 第四章Java核心类库_多线程

    第四章第五节Java核心类库_多线程 多线程 一.线程与进程 1.线程与进程 2.线程调度 二.同步与异步&并发与并行 1. 同步与异步 2. 并发与并行 三.继承Thread 1.代码块 2 ...

最新文章

  1. Python机器学习:训练Tesseract
  2. SAP HANA中的存储过程(sql procedure)
  3. ae saber插件_【AE插件】 用于做动画制作/设计的五个免费插件 非常好用
  4. 主从mysql能过滤指定dml吗_MyCat教程二:mysql主从复制实现 - HG-93
  5. javaweb学习总结(九):通过Servlet生成验证码图片
  6. java dao 单元测试_Spring Service、Dao进行Junit单元测试
  7. (1)Linux进程调度
  8. totolink服务器未响应,TOTOLINK路由器设置后无法上网问题的解决方法
  9. Java开发工程师,每个阶段需要掌握什么重点?
  10. 谈表单的设计 (一) 合理对表单进行布局
  11. php 刷新腾讯云cdn
  12. Grubbs准则建模与分析 C与Matlab实现
  13. 基于系统的软件测试报告,软件系统测试报告模板.doc
  14. 爬网易云音乐动态的坑
  15. 4173: 数学 欧拉函数 思路题
  16. 用Qt实现Q-M算法化简逻辑表达式及Qt项目打包发布方法
  17. Spanning-tree guard features配置案例
  18. 【读书笔记】组合计数中的行列式方法
  19. Java自定义变换产生摘要数据
  20. linux 常见服务

热门文章

  1. stl vector 函数_vector :: back()函数以及C ++ STL中的示例
  2. 客户端通过网口启动可过去的ip_西安交通大学16年3月课程考试《网络组网技术综合训练》作业考核试题...
  3. python mpi开销_GitHub - hustpython/MPIK-Means
  4. ruby hash方法_Hash.fetch()方法以及Ruby中的示例
  5. ruby array_Array.select! Ruby中的示例方法
  6. 程序员进阶之路—如何独当一面
  7. Python:通过SNMP协议获取H3C、华为交换机的VLAN信息及ARP地址表
  8. 十四、PyCharm开发Python利用WMI修改电脑IP、DNS
  9. QT5快速转换路径(/斜杠与\反斜杠转换)
  10. POJ 1804 Brainman (归并排序 -- 求逆序对数)