Java笔记(十九)……多线程
概述
进程:
是一个正在执行中的程序
每一个进程执行都有一个执行顺序,该执行顺序是一个执行路径,或者叫一个控制单元
线程:
就是进程中的一个独立的控制单元,线程在控制着进程的执行
一个进程中至少有一个线程
Java JVM启动的时候会有一个进程java.exe,该进程中至少有一个线程负责Java程序的执行,而且这个线程运行的代码存在于main方法中,该线程称之为主线程,与C类似,java.exe相当于所有进程的父进程,而且JVM启动了不止一个线程,还有负责垃圾回收的线程
创建线程
第一种创建方式:继承Thread类
- 1: class Sell extends Thread
- 2: {
- 3: private int tickets = 100;
- 4: Sell()
- 5: {
- 6: //启动线程
- 7: start();
- 8: }
- 9: //复写Thread类中的run方法,将线程运行所需的代码写到run方法中
- 10: public void run()
- 11: {
- 12: while(tickets > 0)
- 13: {
- 14: System.out.println("tickets = "+tickets--);
- 15: }
- 16: }
- 17: }
第二种创建方式:实现Runnable接口
- 1: class Sell implements Runnable
- 2: {
- 3: private int tickets = 100;
- 4:
- 5: //实现Runnable接口的run方法
- 6: public void run()
- 7: {
- 8: while(tickets > 0)
- 9: {
- 10: System.out.println("tickets = "+tickets--);
- 11: }
- 12: }
- 13: }
- 14: class ThreadDemo
- 15: {
- 16: public static void main(String[] args)
- 17: {
- 18: //将Runnable接口的子类Sell传递给Thread的构造函数,并启动线程
- 19: new Thread(new Sell()).start();
- 20: }
- 21: }
实现方式与继承方式的区别
其实Thread类同样也是实现了Runnable接口,所以我们要的只是run方法,那么我们只要实现Runnable接口即可,这样避免了单继承的局限性,我们在实现Runnable接口的同时还可以继承其他的类,扩展了功能
线程权限问题
线程安全问题--同步
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误
- 1:
- 2: class Sell implements Runnable
- 3: {
- 4: private int tickets = 10;
- 5:
- 6: //实现Runnable接口的run方法
- 7: public void run()
- 8: {
- 9: while(tickets > 0)
- 10: {
- 11: try{Thread.sleep(500);}catch(Exception e){}
- 12: System.out.println(Thread.currentThread().getName()+"..tickets = "+(--tickets));
- 13: }
- 14: }
- 15: }
当我们让线程操作共享数据时,暂停一会,可以发现,每个线程很容易-1剩余票数的错误
解决方法
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不能参与进来执行
Java对多线程的安全问题提供了专业的解决方式,就是同步代码块或者同步函数
synchronized(对象)
{
需要被同步的代码
}
synchronized void show()
{
函数内容
}
- 1: class Sell implements Runnable
- 2: {
- 3: private int tickets = 10;
- 4:
- 5: //实现Runnable接口的run方法
- 6: public void run()
- 7: {
- 8: //加入锁,使代码同步
- 9: synchronized(this)
- 10: {
- 11: while(tickets > 0)
- 12: {
- 13: try{Thread.sleep(500);}catch(Exception e){}
- 14: System.out.println(Thread.currentThread().getName()+"..tickets = "+(--tickets));
- 15: }
- 16: }
- 17: }
- 18: }
我们可以看到,即使中途有睡眠过程,也不再出现错误票数,当然这个例子有一些问题,虽然保证了安全,却只能让一个线程完成操作,解决方法很简单,在while循环内设置判断语句,再加锁即可
对象如同锁,持有锁的线程可以在同步中执行
没有持有锁的线程即使获取了cpu的执行权,也无法执行同步代码
如果同步函数被静态修饰后,如何使用锁?
通过验证,发现不再是this,因为静态方法中也不可以定义this
静态进入内存时,内存中没有本类对象,但是一定有该类的对应的字节码文件对象 类名.class,该对象的类型是Class
所以静态的同步方法是,使用该方法所在类的字节码对象作为锁,即类名.class
- 1: class Tickets
- 2: {
- 3: static int tickets = 10;
- 4: public static void sell()
- 5: {
- 6: //类对象作为锁
- 7: synchronized(Selling.class)
- 8: {
- 9: if(tickets > 0)
- 10: {
- 11: try{Thread.sleep(500);}catch(Exception e){}
- 12: System.out.println(Thread.currentThread().getName()+"..tickets = "+(--tickets));
- 13: }
- 14: }
- 15: }
- 16: }
- 17:
- 18: class Selling implements Runnable
- 19: {
- 20: //实现Runnable接口的run方法
- 21: public void run()
- 22: {
- 23: while(Tickets.tickets> 0)
- 24: {
- 25: Tickets.sell();
- 26: }
- 27: }
- 28: }
同步的前提:
- 必须要有两个或两个以上的线程
- 必须要多个线程使用同一个锁
同步的利弊
好处:解决了多线程的安全问题
弊端:多个线程需要判断锁,较为消耗资源
加入同步之后线程的状态如下
如何编写多线程
- 明确哪些代码是多线程运行代码
- 明确共享数据
- 明确多线程运行代码中哪些语句是操作共享数据的
死锁
死锁其实就是同步中嵌套同步
- 1:
- 2: class A implements Runnable
- 3: {
- 4: String a = "a";
- 5:
- 6: public void run()
- 7: {
- 8: while(true)
- 9: {
- 10: //A抢占A锁
- 11: synchronized(A.class)
- 12: {
- 13: System.out.println("A get 1");
- 14: //A抢占B锁
- 15: synchronized(B.class)
- 16: {
- 17: System.out.println("A get 2");
- 18: System.out.println("A:"+a);
- 19: }
- 20: }
- 21: }
- 22: }
- 23: }
- 24:
- 25: class B implements Runnable
- 26: {
- 27: String b = "b";
- 28:
- 29: public void run()
- 30: {
- 31: while(true)
- 32: {
- 33: //B抢占B锁
- 34: synchronized(B.class)
- 35: {
- 36: System.out.println("B get 1");
- 37: //B抢占A锁
- 38: synchronized(A.class)
- 39: {
- 40: System.out.println("B get 2");
- 41: System.out.println("B:"+b);
- 42: }
- 43: }
- 44: }
- 45: }
- 46: }
- 47: class DeadlockDemo
- 48: {
- 49: public static void main(String[] args)
- 50: {
- 51: new Thread(new A()).start();
- 52: new Thread(new B()).start();
- 53: }
- 54: }
结果如下,A和B都在等待对方释放资源(对应的锁)
Java笔记(十九)……多线程的更多相关文章
- python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法
python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法 同一台机器同时安装 python2.7 和 python3.4不会冲突.安装在不同目录,然 ...
- “全栈2019”Java第九十九章:局部内部类与继承详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十九章:数组详解(中篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第十九章:关系运算符、条件运算符和三元运算符
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- (C/C++学习笔记) 十九. 模板
十九. 模板 ● 模板的基本概念 模板(template) 函数模板:可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计. 语法: template <<模 ...
- Java基础学习笔记十九 IO
File IO概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了.那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再 ...
- Java基础学习笔记十九 File
IO概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了.那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再把这些数据 ...
- Java学习笔记十九:Java中的访问控制修饰符
Java中的访问控制修饰符 一:Java修饰符的种类: 访问修饰符 非访问修饰符 修饰符用来定义类.方法或者变量,通常放在语句的最前端.我们通过下面的例子来说明: public class Hello ...
- swift 笔记 (十九) ——
协议
协议(Protocols) 协议仅是用定义某些任务或者是功能必须的方法和属性. 类似于java里的interface的作用.但协议并不会实现详细的功能. 我猜这个名字源于OO中提到的"契约& ...
随机推荐
- sublime主题推荐
PS:之前在CSDN上写的文章,现在转到博客园~ 寒假的时候发现一个sublime主题,我觉得很赞哦~~推荐给大家~~ 下载方式 step1:ctrl+shift+p 调出command palet ...
- android实现视频图片取缩略图
取缩略图不等同于缩放图片. 缩放图片是保持不失真的情况下缩放处理,并进行平滑处理. 缩略图则不然,允许失真,目的只是取出图片的轮廓. 保存Bitmap图片 private void saveBitma ...
- TIBCO ActiveMatrix BPM 生成daa包脚本
Ant 配置: <?xml version="1.0" encoding="UTF-8" ?> <project name="pro ...
- 用最直白的语言告诉你,hadoop是什么?
hadoop应历史之潮流,随着理论探索.科学技术试验的不断开展,hadoop终于2006年问世,惊天地泣鬼神! hadoop雏形开始于2002年的Apache的Nutch,Nutch是一个开源Java ...
- Razor语法小记
1.代码块中,<text>标签用来输出,如: @{ <text>sdfsdf</text> } 输出Html: sdfsdf
- ASP.NET MVC 3 Razor Views in SharePoint
http://tqcblog.com/2011/01/22/asp-net-mvc-3-razor-views-in-sharepoint/ ASP.NET MVC 3 has just been r ...
- 数据结构---顺序表(C++)
顺序表 是用一段地址连续的存储单元依次存储线性表的数据元素. 通常用一维数组来实现 基本操作: 初始化 销毁 求长 按位查找 按值查找 插入元素 删除位置i的元素 判空操作 遍历操作 示例代码: // ...
- CSS文档流与块级元素和内联元素(文档)
CSS文档流与块级元素(block).内联元素(inline),之前翻阅不少书籍,看过不 少文章, 看到所多的是零碎的CSS布局基本知识,比较表面.看过O'Reilly的<CSS权威指 南> ...
- linux dump 命令详解
功能说明:备份文件系统. 语 法:dump [-cnu][-0123456789][-b <区块大小>][-B <区块数目>][-d <密度>][-f <设备 ...
- 如何启动 SQL Server Agent(SQL Server 配置管理器)
如何启动 SQL Server Agent(SQL Server 配置管理器) SQL Server 2008 R2 其他版本 4(共 6)对本文的评价是有帮助 - 评价此主题 可以从 SQL S ...