目录

1.进程和线程的区别

2.多线程的实现

3.多线程状态及生命周期

4.线程中的主要方法

5.线程的优先级

6.线程的高级操作

7.线程同步

8.死锁

9.Lock对象


1.进程和线程的区别

  • 每个进程都有独立的代码和数据空间,进程的切换会有很大的开销
  • 同一类线程共享代码和数据空间,每个线程有独立运行的栈和程序计数器,线程切换的开销小

2.多线程的实现

(1)  创建线程类
继承Thread类或实现Runnable接口
(2)  通过Thread类构造器来创建线程对象
Thread( )
Thread(Runnable target)
(3)  通过start()方法激活线程对象

例子:

(1)创建继承Thread的类

package test;public class ThreadTest extends Thread{//基层Thread类@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println(Thread.currentThread().getName() + ":" + i + " ");}}}

(2)创建实现Runnable接口的类

package test;public class RunnableTest implements Runnable{//实现Runnable接口@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println(Thread.currentThread().getName() + ":" + i + " ");}}}

(3)测试

package test;public class Test {public static void main(String[] args) {ThreadTest test1 = new ThreadTest();test1.start();//使线程就进入就绪状态test1.setName("test1");//设置test1线程的名字RunnableTest runnable = new RunnableTest();Thread test2 = new Thread(runnable);test2.setName("test2");//设置test2线程的名字test2.start();}
}

3.多线程状态及生命周期

4.线程中的主要方法

例子:

ThreadTest类:

package test;public class ThreadTest extends Thread{//基层Thread类@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println(Thread.currentThread().getName() + ":" + i + " ");}}}

RunnableTest类:

package test;public class RunnableTest implements Runnable{//实现Runnable接口@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println(Thread.currentThread().getName() + ":" + i + " ");}}}

Test类:

package test;public class Test {public static void main(String[] args) {ThreadTest test1 = new ThreadTest();test1.start();//使线程就进入就绪状态test1.setName("test1");try {test1.join();//等待test1线程执行完毕,再执行其它线程} catch (InterruptedException e) {e.printStackTrace();}RunnableTest runnable = new RunnableTest();Thread test2 = new Thread(runnable);test2.setName("test2");test2.start();Thread.yield();//让出CPU,当前线程进入就绪队列等待调度RunnableTest runnable2 = new RunnableTest();Thread test3 = new Thread(runnable2);test3.setName("test3");test3.start();try {Thread.sleep(50);//将当前线程睡眠50毫秒} catch (InterruptedException e) {e.printStackTrace();}}
}

5.线程的优先级

  • Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照线程的优先级来决定应调度哪个线程来执行
  • Java线程的优先级用1~10的整数来表示,越小则优先级越低
  • 但是Java的优先级是高度依赖于操作系统的实现的

Thread类的三个常量,表示常用的线程优先级:

  • Thread.MIN_PRIORITY :1
  • Thread.NORM_PRIORITY:5
  • Thread.MAX_PRIORITY:10

缺省时线程具有NORM_PRIORITY,通过getPriority()和setPriority()获取和设置线程优先级

package test;public class Test {public static void main(String[] args) {ThreadTest test1 = new ThreadTest();test1.start();//使线程就进入就绪状态test1.setName("test1");System.out.println(test1.getPriority());//5,test1线程优先级test1.setPriority(Thread.MIN_PRIORITY);//设置test2线程优先级为1RunnableTest runnable = new RunnableTest();Thread test2 = new Thread(runnable);test2.setName("test2");test2.setPriority(Thread.MAX_PRIORITY);//设置test2线程优先级为10test2.start();RunnableTest runnable2 = new RunnableTest();Thread test3 = new Thread(runnable2);test3.setName("test3");test3.start();test1.setPriority(Thread.NORM_PRIORITY);//设置test3线程优先级为5}
}

6.线程的高级操作

Object类中线程的相关方法:
①void wait() 
导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll() 方法。
②void notify() 
唤醒在此对象监视器上等待的单个线程。
③void notifyAll() 
唤醒在此对象监视器上等待的所有线程。

例子:

①Bread类

package com.waitandnotify.test;/*** 面包程序: 1.如果有面包那么就销售面包 2.如果没有面包那么就生产面包* * * 如果希望实现线程之间互相通知的效果: 1.线程调用的方法必须能够锁定对象的状态,可以是锁定方法,也可以是直接锁定对象 2. 有线程调用wait方法* 让出cpu的时间片 3.有线程调用notifyAll方法,唤醒其他等待对象所得线程 4.2和3在不同的代码块中( 线程中)调用*/
public class Bread {private Boolean isHave = false;// 默认没有面包// 销售面包的方法public synchronized void sale() {if (isHave) {System.out.println(Thread.currentThread().getName() + "销售面包的方法sale()");// 销售完面包没了isHave = false;this.notifyAll();// 虽然唤醒所有等着面包对象的锁的人,实际真正抢到时间片的线程只有一个} else {// 销售面包的人,没有面包销售时就等着,等生产者生产面包之后通知他try {System.out.println(Thread.currentThread().getName() + "在等待对象的锁");this.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "有面包了,完成sale方法");}}// 生产面包的方法public synchronized void produce() {// p1 p2if (!isHave) {// p1 p2System.out.println(Thread.currentThread().getName() + "生产面包的方法");// 销售完面包没了isHave = true;this.notifyAll();// 虽然唤醒所有等着面包对象的锁的人,实际真正抢到时间片的线程只有一个} else {// 生产面包的人,没有面包销售时就等着,等着销售面包之后通知他try {System.out.println(Thread.currentThread().getName() + "在等待对象的锁");this.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "没有面包了,完成produce方法");}}
}

②ProductThread类

package com.waitandnotify.test;public class ProductThread implements Runnable {private Bread bread;public ProductThread(Bread bread) {this.bread = bread;}@Overridepublic void run() {for (int i = 0; i < 200; i++) {bread.produce();}}}

③SaleThread类

package com.waitandnotify.test;public class SaleThread implements Runnable{private Bread bread = null;public SaleThread(Bread bread) {this.bread = bread;}@Overridepublic void run() {for (int i = 0; i < 200; i++) {bread.sale();}}
}

④Test测试类

package com.waitandnotify.test;public class Test {public static void main(String[] args) {Bread bread = new Bread();SaleThread sale1 = new SaleThread(bread);ProductThread prod1 = new ProductThread(bread);Thread s1 = new Thread(sale1);s1.setName("销售者1");Thread p1 = new Thread(prod1);p1.setName("生产者1");s1.start();p1.start();}
}

7.线程同步

  • 有时两个或多个线程可能会试图同时访问一个资源
  • 为了确保在任何时间点一个共享的资源只被一个线程使用,使用了synchronized关键字实现“同步
  • 当一个线程运行到需要同步的语句后,CPU不去执行其他线程中的、可能影响当前线程中的下一句代码的执行结果的代码块,必须等到下一句执行完后才能去执行其他线程中的相关代码块,这就是线程同步

(1)实现线程同步的两种方式

①synchronized方法

synchronized void methodA() {  }

②synchronized语句

synchronized (Object) {
    //要同步的语句
}

(2)注意事项

受到synchronized保护的程序代码块和方法中,要访问的对象属性必须设定为private,因为如果不设定为private,那么就可以用不同的方式来访问它,这样就达不到保护的效果了

(3)例子

Ticket类

package com.ticket.test;public class Ticket implements Runnable {private int number = 100;// 一共100张票public synchronized void purchase() {// 购票if (number > 0) {System.out.println(Thread.currentThread().getName() + "买了票:No." + number);number--;}}@Overridepublic void run() {for (int i = 0; i < 10; i++) {purchase();}}public static void main(String[] args) {Ticket ticket = new Ticket();Thread t1 = new Thread(ticket);t1.setName("小明");Thread t2 = new Thread(ticket);t2.setName("小红");Thread t3 = new Thread(ticket);t3.setName("小刚");//三个人同时抢票t1.start();t2.start();t3.start();}
}

8.死锁

(1)概念

两个线程,彼此在等待对方占据的锁

(2)锁归还的几种方式

  • 基本上执行完同步的程序代码后,锁就会自动归还;
  • 用break语句跳出同步的语句块,不过这对于写在方法声明的synchronized没有作用;
  • 遇到return语句;
  • 遇到了异常;

(3)例子

Thread1类

package com.dielock.test;public class Thread1 extends Thread{Object o1 = null;Object o2 = null;public Thread1(Object o1, Object o2){this.o1 = o1;this.o2 = o2;}@Overridepublic void run() {synchronized (o1) {try {Thread.sleep(500);synchronized (o2) {System.out.println("o2");}} catch (InterruptedException e) {e.printStackTrace();}}}
}

Thread2类:

package com.dielock.test;public class Thread2 extends Thread{Object o1 = null;Object o2 = null;public Thread2(Object o1, Object o2){this.o1 = o1;this.o2 = o2;}@Overridepublic void run() {synchronized(o2){try {Thread.sleep(500);synchronized(o1){System.out.println(o1);}} catch (InterruptedException e) {e.printStackTrace();}}}
}

Test测试类:

package com.dielock.test;public class Test {public static void main(String[] args) {Object o1 = new Object();Object o2 = new Object();Thread1 t1 = new Thread1(o1, o2);t1.setName("t1");t1.start();Thread2 t2 = new Thread2(o1, o2);t2.setName("t2");t2.start();}
}

9.Lock对象

如何锁对象?

  • 不要锁方法
  • 把进入面包房要执行的工作代码放入锁对象的代码块中
  • 注意事项:如果访问对象的属性,那么属性必须是私有的
package com.ticket.test;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Ticket implements Runnable {private int num = 100;// 一共一百张票private Lock lock = new ReentrantLock();//创建锁对象@Overridepublic void run() {lock.lock();//上锁for (int i = 0; i < 10; i++) {//一人买十张if (num > 0) {System.out.println(Thread.currentThread().getName() + "买了No." + num);num--;} else {break;}}lock.unlock();//解锁}public static void main(String[] args) {Ticket ticket = new Ticket();Thread t1 = new Thread(ticket);Thread t2 = new Thread(ticket);Thread t3 = new Thread(ticket);t1.setName("XiaoHong");t2.setName("XiaoLiu");t3.setName("XiaoXin");t1.start();t2.start();t3.start();}
}

输出结果:

XiaoHong买了No.100
XiaoHong买了No.99
XiaoHong买了No.98
XiaoHong买了No.97
XiaoHong买了No.96
XiaoHong买了No.95
XiaoHong买了No.94
XiaoHong买了No.93
XiaoHong买了No.92
XiaoHong买了No.91
XiaoLiu买了No.90
XiaoLiu买了No.89
XiaoLiu买了No.88
XiaoLiu买了No.87
XiaoLiu买了No.86
XiaoLiu买了No.85
XiaoLiu买了No.84
XiaoLiu买了No.83
XiaoLiu买了No.82
XiaoLiu买了No.81
XiaoXin买了No.80
XiaoXin买了No.79
XiaoXin买了No.78
XiaoXin买了No.77
XiaoXin买了No.76
XiaoXin买了No.75
XiaoXin买了No.74
XiaoXin买了No.73
XiaoXin买了No.72
XiaoXin买了No.71

Java第十一天笔记01——多线程编程相关推荐

  1. [PYTHON] 核心编程笔记(18.多线程编程)

    18.1 引言/动机 18.2 线程和进程 18.2.1 什么是进程(重量级进程)? 计算机程序只不过是磁盘中可执行的,二进制(或其他类型)的数据,他们只有在被读取到内存中,被操作系统调用时才开始他们 ...

  2. VB.NET学习笔记:多线程编程

    在<多线程加委托实现等待窗体(loading正在加载界面),运行超时可以取消操作>一文中使用到了多线程编程,在这里做个笔记. 我们继续使用<再谈委托--同步.异步.Lambda 表达 ...

  3. 【cpp学习笔记】多线程编程

    1.前言 在学习利用多线程来实现多模型的目标检测时,接触到了 condition_variable.future等多线程编程知识,感觉自己对这方面的知识还不熟悉,于是便找了一些学习资料进行学习. 2. ...

  4. 鸿钧老祖 数据结构笔记01:编程面试过程中常见的10大算法(java)

    以下是在编程面试中排名前10的算法相关的概念,我会通过一些简单的例子来阐述这些概念.由于完全掌握这些概念需要更多的努力,因此这份列表只是作为一个介绍.本文将从Java的角度看问题,包含下面的这些概念: ...

  5. JAVA学习笔记--4.多线程编程 part5.这些年的那些坑

    2019独角兽企业重金招聘Python工程师标准>>> 基本要求 没指定线程name. 没有限定线程个数. Thread#stop等被废弃的方法不安全,详见TODO. 注意锁作用的对 ...

  6. JAVA学习笔记--4.多线程编程 part1.背景知识和内存模型

    2019独角兽企业重金招聘Python工程师标准>>> 背景知识 CPU Cache 如上简易图所示,在当前主流的CPU中,每个CPU有多个核组成的.每个核拥有自己的寄存器,L1,L ...

  7. Java第十二天笔记01——网络编程

    1.Sockete原理 是网络应用程序编程的接口和一种机制 用套接字中的相关函数来建立连接和完成通信 Socket可以看成在两个程序进行通讯连接中的一个端点 2.基于TCP的Socket编程 利用TC ...

  8. 2022.0727学习Java笔记之多线程编程(二)

    多线程的操作方法 多线程的操作方法基本上都在Thread类之中定义的,所以研究方法也就是一个Thread类的翻译,那么下面主要看三组方法. 1.线程的命名和取得 在整个多线程的操作之中,名称是最重要的 ...

  9. JAVA高并发学习笔记(二) 多线程基础

    1.1什么是线程 线程是进程(程序在计算机上的一次执行活动)内的执行单元 进程是以独立于其他进程的方式运行的,进程间是互相隔离的.一个进程无法直接访问另一个进程的数据.进程的资源诸如内存和CPU时间片 ...

最新文章

  1. 在bootstrap ace样式框架上修改的后台管理型模板(Tab页后台管理模板)
  2. VUE 事件获取当前组件的属性
  3. Android 常见adb命令
  4. Linux 下关于网络的几个命令
  5. 查看Linux系统架构的命令,查看linux系统是哪种架构:AMD、ARM、x86、x86_64、pcc 或 查看Ubuntu的版本号
  6. 推断股票强弱最有效的一个方法
  7. 操作系统——磁盘寻道练习题及答案
  8. linux遍历目录漏洞,Mutiny 多个目录遍历漏洞(CVE-2013-0136)
  9. 常见的反爬措施:UA反爬和Cookie反爬
  10. csr 蓝牙驱动_【BTS001】开源蓝牙协议栈BTStack初体验
  11. BZOJ4898/5367 Apio2017商旅(分数规划+floyd)
  12. 数据包络(DEA)分析法python实现
  13. 阿里云认证有什么用?考哪个比较好?
  14. 五笔86和汉字对照表
  15. UVALive - 4987 (dp+贪心)
  16. map的基本使用-go篇
  17. freeswitch-PSTN
  18. 新的Novidade漏洞利用工具包目标瞄准家用和SOHO路由器
  19. 开启硬件辅助虚拟化——Intel虚拟化之旅
  20. mysql中的mmr

热门文章

  1. 构造函数中new在执行时都做了哪些事情?
  2. 宇称不守恒说了啥?杨振宁和李政道的发现有多大意义
  3. 【kratos】kratos 框架使用新的,还是非常好的技术框架,还要继续学习,掌握了proto 文件的使用、wire的使用就方便了。
  4. 爬取豆瓣电影中各种类型电影名称与评分
  5. FL Studio12中Fruity Blood Overdrive插件使用教程
  6. 小程序选择手机图片后 压缩图片 转码base64
  7. hbase数据库 数据存入_七个星期中的七个数据库– Hbase第二天
  8. 终于搞懂了,用大白话给你解释Zookeeper的选举机制,包教会
  9. ValueError: The number of elements in ‘fill‘ does not match the number of bands of the image (3 != 4
  10. ROS2学习tf2坐标变换