Java学习:多线程
多线程
线程是依赖于进程而存在的。
A:进程 正在运行的应用程序
B:线程 进程的执行路径,执行单元
多线程的两种方案:
继承Thread类:需重写run()方法。
实现Runable接口
启动线程用的是 start()方法
start()和run()的区别
start():1.开启线程 2.执行run()方法里面的代码
run():执行的是线程里面执行的代码,并不会开启线程
为什么要重写run()
因为每个线程需要执行的代码都是都是不一样的,
我们需要将每个线程自己独立执行的代码写到run()方法中执行
线程不可以多次启动
线程的调度和控制
线程休眠(Thread.sleep(毫秒值))
线程名称(setName(),getName();)
线程的调度及优先级setPriority(10)(注意默认值是5,区间在1-10之间)
什么叫线程优先级:说白了就是设置你抢占cpu执行权抢占到的概率
多线程安全问题
A:是否是多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
如何解决多线程安全问题
线程安全执行效率就低
A:同步代码块(测试不是同一个锁的情况,测试是同一个锁的情况)
synchronized(对象) {
需要被同步的代码。
}
需求:1.测试不是同一把锁的时候线程安全吗? 2.如果是同一把锁线程安全吗?
两个问题:1.对象是什么 ?
答:任意对象 ,相当于是一把锁,只要线程进去就把锁锁上
2.需要同步的代码?
答:被线程执行的代码
B:锁对象问题
a:同步代码块(定义一个抽象类,里面专门定义一个锁)
任意对象
b:同步方法(仅适用于实现runable接口)
public synchronized void sellTicket(){同步代码}
this
c:静态同步方法
类的字节码对象
public static synchronized void sellTicket() {
需要同步的代码
}
代码如下:
1 //同步代码块 2 synchronized (new Object()) {//t1,t2,t3三个线程不共享同一把锁每个线程都有自己的议案锁 3 //synchronized (obj) {//这样3个线程才可以共享同一把锁 4 if (ticket>0) { 5 //考虑到实际的生活中,我们需要给每一个线程加入一定的延迟,模拟一下这种效果 6 try { 7 Thread.sleep(100); 8 /** 9 * 分析:为什么会出现两张100张票 10 * t1抢占到cpu的执行权,此时ticket=100,但是此刻休眠了 11 * 此时被t2抢占到了cpu的执行权,此时ticket=100, 12 * t1,t2分别睡了100毫秒之后,分别醒来了。。 13 * t1此时出售第100张票 14 * t2此时出售第100张票 15 */ 16 17 /** 18 * 分析:为什么会出现0张票和-1张票 19 * 假设此时票池中仅剩1张票了, 20 * t1进来休眠了 21 * t2进来休眠了 22 * t3进来休眠了 23 */ 24 } catch (InterruptedException e) { 25 // TODO Auto-generated catch block 26 e.printStackTrace(); 27 } 28 29 System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"张票"); 30 /** 31 * t1醒来,出售的是第1张票,此时tickt=0 32 * t2醒来,出售第0张票,此时ticket=-1 33 * t3醒来,出售第-1张票,此时ticket=-2 34 */ 35 36 /** 37 * ticket--这个动作一共包含几步: 38 * 1.打印出ticket此刻本身的值 39 * 2.ticket自减1 40 * 3.将自减之后的ticket的最新的值赋值给变量ticket 41 */ 42 } 43 } 44 //当被同步的代码执行完毕之后,t1手里拿着的obj这个锁才会被释放, 45 //t1,t2,t3重新抢占cpu的执行权,谁抢到了继续拿着obj这个锁,执行同步代码块中的内容 46
同步代码块
1 MyThread mt = new MyThread(); 2 3 //创建三个窗口 4 Thread t1 = new Thread(mt); 5 Thread t2 = new Thread(mt); 6 Thread t3 = new Thread(mt); 7 8 //给每一个窗口设置姓名 9 t1.setName("窗口一"); 10 t2.setName("窗口二"); 11 t3.setName("窗口三"); 12 13 //开启窗口进行售票 14 t1.start(); 15 t2.start(); 16 t3.start();
测试方法
运行部分结果如图;
同步方法代码:
1 同步方法:同步方法是将synchronized关键字加到方法上,同步方法的锁是this 2 private synchronized void sellTicket() { 3 if (ticket>0) { 4 //考虑到实际的生活中,我们需要给每一个线程加入一定的延迟,模拟一下这种效果 5 try { 6 Thread.sleep(100); 7 } catch (InterruptedException e) { 8 // TODO Auto-generated catch block 9 e.printStackTrace(); 10 } 11 12 System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"张票"); 13 14 } 15 }
同步方法
静态同步方法:
1 private static synchronized void sellTicket() { 2 if (ticket>0) { 3 //考虑到实际的生活中,我们需要给每一个线程加入一定的延迟,模拟一下这种效果 4 try { 5 Thread.sleep(100); 6 } catch (InterruptedException e) { 7 // TODO Auto-generated catch block 8 e.printStackTrace(); 9 } 10 11 System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"张票"); 12 13 }
静态同步方法
匿名内部类的方式使用多线程
new Thread() {
public void run() {
...
}
}.start();
new Thread(new Runnable(){
public void run() {
...
}
}).start();
联系代码如下:
1 //方式1: 2 new Thread(){ 3 //重写的方法 4 @Override 5 public void run() { 6 for (int i = 0; i <10; i++) { 7 System.out.println(i); 8 } 9 } 10 }.start(); 11 12 //方式2 13 new Thread(new Runnable() { 14 @Override 15 public void run() { 16 for (int i = 0; i <10; i++) { 17 System.out.println(i); 18 } 19 } 20 }).start();
匿名内部类
JDK5的Lock锁,我们之前造的所有的锁都没有手动释放锁
static Lock lock = new ReentrantLock();
枷锁:lock.lock();
释放锁:lock.unlock();
可以让我们明确的知道在哪里加锁和释放锁。
依然写一个卖票的demo,用lock枷锁释放锁,
为了保证我们创建的锁一定会被释放,用一下代码进行改进
try{....}finally{.....}
1 //定义100张票 2 int ticket = 100; 3 Object obj = new Object(); 4 //创建一个锁 5 Lock lock = new ReentrantLock(); 6 7 @Override 8 public void run() { 9 while (true) { 10 try{ 11 //加上锁,获取锁 12 lock.lock(); 13 if (ticket>0) { 14 //考虑到实际的生活中,我们需要给每一个线程加入一定的延迟,模拟一下这种效果 15 try { 16 Thread.sleep(100); 17 } catch (InterruptedException e) { 18 // TODO Auto-generated catch block 19 e.printStackTrace(); 20 } 21 22 System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"张票"); 23 } 24 }finally{ 25 //这里面的代码一定会被执行 26 //释放锁 27 lock.unlock(); 28 } 29 } 30 31 }
lock锁
死锁问题
同步嵌套,锁里面套了一个锁,出现同步嵌套
1 boolean flag; 2 3 //提供一个有参构造 4 public DieThread(boolean flag){ 5 this.flag = flag; 6 } 7 8 @Override 9 public void run() { 10 if (flag) { 11 synchronized (MyLock.objA) { 12 System.out.println("if"+"objA"); 13 synchronized (MyLock.objB) { 14 System.out.println("if"+"objB"); 15 } 16 } 17 18 }else { 19 synchronized (MyLock.objB) { 20 System.out.println("else"+"objB"); 21 synchronized (MyLock.objA) { 22 System.out.println("else"+"objA"); 23 } 24 } 25 26 } 27 28 }
死锁问题
线程等待和唤醒机制(案例演示:waitThread,NotifyThread,MyLock,Test)
锁对象调用wait()锁对象调用notify()
注意:
wait和sleep的区别
线程等待,在等待的同时释放锁,而sleep()方法在执行的过程中是不会释放锁的
1 //让等待线程处于等待状态 2 try { 3 MyLock.obj.wait();//当线程处于等待状态的时候,线程就不会继续往下执行了 4 //线程在处于等待的时候,会释放掉自己手中的锁 5 //sleep()这个方法,在线程休息的时候会释放锁码? 6 //答:不会 7 } catch (InterruptedException e) { 8 // TODO Auto-generated catch block 9 e.printStackTrace(); 10 } 11 } 12 System.out.println("我被唤醒了");
wait
1 public void run() { 2 synchronized (MyLock.obj) { 3 //唤醒等待线程 4 MyLock.obj.notify();//唤醒正在等待的线程,唤醒的等待线程的锁对象,必须和等待线程的锁对象一致 5 } 6 }
View Code
1 WaitThread wt = new WaitThread(); 2 wt.start(); 3 4 //睡上5秒钟之后唤醒等待线程 5 try { 6 Thread.sleep(5000); 7 } catch (InterruptedException e) { 8 // TODO Auto-generated catch block 9 e.printStackTrace(); 10 } 11 12 13 //创建唤醒线程对象 14 NotifyThread nt = new NotifyThread(); 15 nt.start();
View Code
转载于:https://www.cnblogs.com/shaofanglazi/p/6875115.html
Java学习:多线程相关推荐
- Java学习--多线程
1.实现多线程 1.1简单了解多线程[理解] 是指从软件或者硬件上实现多个线程并发执行的技术. 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能. 1.11多线程实现三种方式( ...
- java 学习~多线程通信 使用共享变量 例子和解释
多线程互相通信一般使用共享变量.. 完整验证代码: main 方法 public class Test5 {public static void main(String[] args) {Datax ...
- Java学习笔记(7)——Java基础之IO多线程网络思维导图
Java面向对象学习笔记之:包括IO(字节流,字符流,节点流,处理流).线程(线程创建,线程控制,线程同步).网络(TCP Scoket, UDP Scoket)(全屏观看Java学习笔记(7)-- ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- Java学习笔记5-1——多线程
目录 前言 核心概念 线程创建 继承Thread类 实现Runnable接口 上述两个方法小结 实现Callable接口 并发问题简介 静态代理模式 线程状态 线程停止(stop) 线程休眠(slee ...
- Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍
1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...
- java多线程阶乘_【java学习记录】11.用多线程实现阶乘的计算过程和结果的读取(thread类ReadThread )...
(源码在上传的压缩包"[java学习记录]11.多线程实现阶乘计算(Thread类和Runnable接口)"中可看到,该压缩包可下载)java * 采用Thread类的子类实现线程 ...
- Java学习记录五(多线程、网络编程、Lambda表达式和接口组成更新)
Java学习记录五(多线程.网络编程.Lambda表达式和接口组成更新) Java 25.多线程 25.1实现多线程 25.1.1进程 25.1.2线程 25.1.3多线程的实现 25.1.4设置和获 ...
- Java 学习 Day17 多线程
Java 学习 Day17 文章目录 Java 学习 Day17 一.基本概念:程序.进程.线程 二.线程的创建和使用 三.多线程的创建,方式一:继承于Thread类 四. 创建多线程的方式二:实现R ...
- Java学习笔记2 多线程简单总结
多线程简单总结 1. 相关概念 1.1 线程与进程 进程 线程 1.2 线程调度 分时调度 抢占式调度 1.3 同步与异步 同步 异步 1.4 并发与并行 并发 并行 2. 创建线程 2.1 继承Th ...
最新文章
- 窗口之间传递消息的一个方法
- 三行代码实现快速排序
- 浅谈ASP.NET Forms验证
- Nagios 请检查HTTP服务器关于该CGI的访问权限设置
- 这个副业清单,总有一个适合你!
- python获取视频缩略图_用 Python 代码生成视频的缩略图
- flex 布局,flex-grow 宽度未等比放大问题解决办法
- stm32 薄膜键盘原理_雷蛇发布第二代轻机械键盘,你了解什么是轻机械键盘吗?...
- 十篇论文攻克自然语言处理底层原理!推荐大家复现!
- 看《墨攻》理解IoC—Spring底层核心
- FPGrowth算法理论
- 【已解决】Remove redundant parentheses等Python错误大全
- 【Mac小技巧】如何改变顶部状态栏的颜色
- 程序员能成为自由职业者吗?
- python怎么实现模糊找色_Python下尝试实现图片的高斯模糊化
- SQL Server 2008 R2导出数据脚本和导入数据库脚本的方法(原创+转载)
- 做共享软件的一些心得与经验
- 数据时代的大数据技术,主要包括哪些内容?
- 文件上传下载遇到的异常
- Apple ProRes编码
热门文章
- oracle 游标取字段名称,Oracle使用游标查询指定数据表的所有字段名称组合而成的字符串...
- 整数规划 Integer Programming 是什么
- mtk6595能否运行linux,“被妖魔化”的联发科MTK6595到底如何?
- java servlet JSP 区别_servlet和jsp的区别
- 基于SSM的NBA篮球球队运营系统
- linux新建虚拟机到图形化界面
- layui实现后台表格数据显示--学生管理系统(layui搜索,删除,批量删除,增加,修改,php接口后台)
- L3_01 01背包和最小序列
- Dubbo 优雅停机演进之路
- Elasticsearc 6.x以后不再支持mapping下多个type