------- android培训、java培训、期待与您交流! ----------
11.01 概述
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread
对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。
当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main
方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:
- 调用了
Runtime
类的exit
方法,并且安全管理器允许退出操作发生。 - 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到
run
方法之外的异常。
创建新执行线程有两种方法。一种方法是将类声明为 Thread
的子类。该子类应重写 Thread
类的 run
方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:
class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }
然后,下列代码会创建并启动一个线程:
PrimeThread p = new PrimeThread(143); p.start();
创建线程的另一种方法是声明实现 Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:
class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143); new Thread(p).start();
每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。
/*
进程:是一个正在执行中的程序
每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元
线程:就是进程中一个独立的控制单元
线程在控制着进程的执行
一个进程中至少有一个线程
Java Vm 启动的时候就有一个进程java.exe
该进程中至少有一个线程在负责java程序的执行
而且这个线程运行的代码存在于main方法中
该线程称之为主线程
扩展:其实jvm,启动的时候不只一个线程,还有负责垃圾回收机制的线程
1。如何在自定义的代码中,自定义一个线程呢?
通过对api(Application Programming Interface,应用程序编程接口)的查找,java已经提供了对线程这类事物的描述,就是Thread类
11.02 创建线程-继承Thread类
创建线程的第一种方式:继承Thread类
步骤;
1,定义类,继承Thread类
2。复写run方法
目的:将自定义的代码存储在run方法中,让线程运行
3,创建一个对象,执行start方法,
该方法有两个作用:启动线程,调用run
发现运行结果每一次都不同
因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行
明确一点,在某一个时刻,只能有一个程序执行(多核除外)
cpu在做着快速的切换,以达到看上去是同时运行的效果
我们可以形象把多线程的运行形容为在互相抢夺cpu的执行权
这就是多线程的一个特性:随机性,谁抢到谁执行,至于执行多长,cpu说的算
这个过程是随机的
11.03 run start的特点
为什么要覆盖run方法呢?
Thread用于描述线程
该类就定义了一个功能(run function),用于存储线程要运行的代码,该功能就是run方法
也就是Thread类中的run方法,用于存储线程要运行的代码(主线程存在于main方法中)
*/
class Demo extends Thread { public void run() { for (int x=0;x<60;x++) System.out.println("demo run--"+x); } } class ThreadDemo { public static void main(String[] args) { Demo d = new Demo();//创建好了一个线程 d.start();//开启线程,并调用该线程的run方法 //d.run();//仅仅是调用了对象方法,线程没有启动,是主线程的动作 for (int x = 0;x < 60;x++ ) { System.out.println("Hello World!--"+x); } } }
11.04 线程练习
第11天-06-多线程(获取线程对象以及名称)
/*
线程都有自己的名称,通过getName函数获取
Thread-编号,该编号从0开始
static Thread currentThread();获取当前线程对象
设置线程名称:setName或者构造函数(super关键字)
*/
class Test extends Thread { // private String name; Test(String name) { //this.name = name;//构造函数和成员变量不能在成员方法中,是独立存在的 super(name); } public void run() { for (int x= 0;x < 60; x++) { System.out.println((Thread.currentThread()==this)+"--test--"+x+"--"+this.getName()); } } } class ThreadTest { public static void main(String[] args) { Test t1 = new Test("one--"); Test t2 = new Test("two++"); t1.start(); t2.start(); for (int x = 0;x < 60; x++) { System.out.println("--main--" + x); } } }
11.05 线程运行状态
11.07 售票的例子
11.08实现RUNABLE接口
/*
需求:简单的卖票程序
多个窗口同时卖票
程序运行后发现了一个问题:
1.卖票的时候有重复行为,这时考虑将tick设置为静态共享数据
但是静态有其局限性;
2.也可以考虑创建一个线程让他执行四次,但是运行会报告线程异常,一个线程被启动了四次,明显是
一种浪费而且不符合程序设计初衷
3。这时就考虑线程创建的问题了
------------------------------
线程创建的第二种方式:实现Runnable接口
步骤:
1.定义类实现Runnable接口
2,覆盖Runnable接口中的run方法
将线程要运行的代码存在于该run方法中
3,通过Thread类建立线程对象
4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
5.调用Thread类的strat方法开启线程并调用Runnable接口子类的run方法
------------------------------------
实现方式和继承方式有什么区别吗?
继承方式时,只能单继承,想要实现多线程就要创建一个子类对象,子类对象运行的时候会调用run方法,多个对象调用的时候会重复调用run方法中的代码,等于多个人在做一件事情,是一种浪费
实现方式时,将Runnable接口的子类创建的对象作为参数传递给Thread的构造函数,这时Thread类创建的对象会运行多个线程,但是执行的代码是同一块代码,等于多个人在一起做一件事情,效率更高也没有浪费
-------------------------------------------------------------
实现方式好处:避免了单继承的局限性
在定义线程时,建议使用实现方式
*/
class Ticket implements Runnable { private //static int tick = 100; public void run() { while (true) { if (tick > 0) System.out.println("sale : "+ tick--); } } } class TicketDemo { public static void main(String[] args) { Ticket t = new Ticket();/该对象非线程 Thread t1=new Thread(t); Thread t2=new Thread(t); Thread t3=new Thread(t); Thread t4=new Thread(t); t1.start(); t2.start(); t3.start(); t4.start();//这四个对象此时调用start方法调用的run方法,调用的Ticket类的对象只有一个,就是Runnable类接口的子类所创建的Ticket类对象t } }
11.09 多线程的安全的问题
11.10同步代码块
/*
通过分析,发现打印出0.-1.-2等错票
多线程的运行出现了安全问题:
问题的原因:
当多条线程在操作同一个共享数据时,一条线程对这个数据只执行了一部分,,还没有执行完
另一个线程参与进来执行,导致共享数据的错误(代码中tick的判断出现了错误)
解决方案:
对多条线程执行操作共享数据时,只能让一个线程都执行完,在执行过程中其他不可以参与执行
java中内置了解决方式:
同步代码块
synchronized(对象)
{
需要被同步的代码
}
同步的前提;
1。必须要有两个或两个以上的线程
2。必须是多个线程使用同一个锁
必须保证同步中只有一个线程在运行
好处;解决了多线程的安全问题
弊端:多个线程都需要判断锁,较为消耗资源
*/
class Ticket implements Runnable { private int tick = 10000; Object obj = new Object(); public void run() { while (true) { synchronized (obj) { if (tick > 0) try { Thread.sleep(10); } catch (Exception e) { }//这个异常不能抛,因为是接口类型 System.out.println(Thread.currentThread().getName()+"sale : "+ tick--); } } } } class TicketDemo2 { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t); Thread t3=new Thread(t); Thread t4=new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); } }
11.11 同步函数
/*
需求:
银行有一个金库,有两个储户分别存300元,每次存100,存3次
目的:该程序是否有安全问题,如果有,如何解决?
如何找问题;
1,明确哪些代码是多线程运行代码
2,明确共享数据
3。明确多线程运行代码中哪些语句是操作共享数据的
*/
class Bank { private int sum; Object obj = new Object(); public synchronize//或则 void add(int n) { synchronized(obj) { sum = sum + n; try { Thread.sleep(10); } catch (Exception e) { }//这个函数可以抛出 System.out.println("sum="+sum); } } } class Cus implements Runnable { private Bank b = new Bank(); public void run() { for (int x = 0; x < 3; x++) { b.add(100); } } } class BankDemo { public static void main(String[] args) { Cus c = new Cus(); Thread t1 = new Thread(c); Thread t2 = new Thread(c); t1.start(); t2.start(); } }
11.12 同步函数的锁是this
/*
同步函数使用的锁是this
*/
class Ticket implements Runnable { private int tick = 100; boolean flag = true; public void run() { if (flag) { while (true) { synchronized(this) { if(tick > 0) { try{Thread.sleep(10);}catch (Exception e){} System.out.println(Thread.currentThread().getName()+"--code--"+tick--); } } } } else while (true) show(); } public synchronized void show() { if (tick > 0) { try{Thread.sleep(10);}catch (Exception e){} System.out.println(Thread.currentThread().getName()+"--show--"+tick--); } } } class ThislockDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start(); try{Thread.sleep(10);}catch (Exception e){} t.flag = false; t2.start(); } }
11.13 静态同步函数的锁是Class对象
/*
如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证发现不再是this了
静态方法中也不会有this
静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象
类名.class,该对象的类型是Class
静态的同步方法使用的锁是该方法所在类的字节码文件对象,类名.class
*/
class Ticket implements Runnable { private static int tick = 100; //Object obj = new Object(); boolean flag = true; public void run() { if (flag) { while (true) { synchronized(Ticket.class) { if(tick > 0) { try{Thread.sleep(10);}catch (Exception e){} System.out.println(Thread.currentThread().getName()+"--code--"+tick--); } } } } else while (true) show(); } public static synchronized void show() { if (tick > 0) { try{Thread.sleep(10);}catch (Exception e){} System.out.println(Thread.currentThread().getName()+"--show--"+tick--); } } } class StaticMethodDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start(); try{Thread.sleep(10);}catch (Exception e){} t.flag = false; t2.start(); } }
11.14 单例设计模式 懒汉式
class Single//懒汉式 { private static Single s = null; private Single(){} public static //synchronized Single getInstance()//可以用同步函数或者同步代码块解决多线程访问的安全问题,但是相比较同步代码块效率更高 { if (s==null)//多线程访问时会存在安全问题,需要同步 { synchronized(Single.class)// 什么意思? { if(s==null) s = new Single(); } } retrun s; } } //饿汉式 class Single { private static final Single s = new Single(); private Single(){} public static getInstance() { return s; } }
11.15多线程-死锁
/*
死锁;
同步中嵌套同步
*/class Ticket implements Runnable { private int tick = 100; boolean flag = true; Object obj = new Object(); public void run() { if (flag) { while (true) { synchronized(obj) { show(); } } } else while (true) show(); } public synchronized void show() { synchronized(obj) { if(tick > 0) { try{Thread.sleep(10);}catch (Exception e){} System.out.println(Thread.currentThread().getName()+"--code--"+tick--); } } } } class DeadLockDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start(); try{Thread.sleep(10);}catch (Exception e){} t.flag = false; t2.start(); } }
简单版本:
class Test implements Runnable { private boolean flag; Test(boolean flag) { this.flag=flag; } public void run(); { if(flag) { while(true) { synchronized(locka) { System.out.println("if lcoka "); synchronized(lockb) { System.out.println("if lockb"); } } } } else() { synchronized(lockb) { System.out.println("else lockb"); synchronized(locka) { System.out.println("else locka"); } } } } } class MyLock { Object locka=new Object(); Object lockb=new Object(); } class { public static void main(String[] args) { Thread t1 = new Thread(new Test(true)); Thread t2 = new Thread(new Test(false)); t1.start(); t2.start(); } }
相关推荐
NULL 博文链接:https://huangminwen.iteye.com/blog/1157983
NULL 博文链接:https://lvwenwen.iteye.com/blog/1470696
当一个进程中线程有多个时,是多线程。 为什么要用多线程 1,让计算机"同时"做多件事情,节约时间。 2,后台运行程序,提高程序的运行效率.。 3,多线程可以让程序"同时"处理多个事情。 4,...
黑马程序员_张孝祥_Java多线程与并发库,视频+代码+资料
1、 面向对象、跨平台性、健壮性、安全性、可移植性、多线程性、动态性等。 2、 JRE(Java Runtime Environment,Java 运行时环境),它相当于操作系统部分,提供了 Java 程序运 行时所需要的基本条件和许多 Java ...
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
传智播客_Java培训_毕向东_Java基础[05-多线程]系黑马程序员_毕向东_Java基础视频教程
|--利用FinalHttp实现多线程断点续传 |--加密之MD5 |--动画Animation详解 |--动画之view左右抖动 |--动画之移动动画 |--动画之组合动画 |--动画之缩放动画ScaleAnimation |--反序列化对象 |--发送短信 读天气 调音量...
日本资-深技术作家、《程序员的数学》作者结城浩执笔,264张图表(UML类图、时序图、Timethreads图等)穿插文中,通过类比手法和浅显的语言,逐一讲解与多线程和并发处理相关的12种设计模式。每章附带练习题和答案,...
这是一个java写的拼图游戏,用了swing、多线程等知识,可以设置行数列、列数、还有使用多线程写的游戏动画,拼图的图块具有磁贴设计,代码封装性较强,容易移植,纯原创。
精选12种与多线程和并发处理相关的设计模式 264张图表 + 300段Java示例程序 = 轻松学习多线程编程 日本经典多线程入门书,原版长销11年! 本书适合以下读者阅读 a.对多线程感兴趣的人 b.对Java编程感兴趣的人 c.对...
萌新做的一个简单的Java拼图游戏 启动类:pers.sept.jigsaw1.swing下的...多线程。 下拉列表选择数字可以切换关卡图片,最后的“+”,可以添自己的图片到关卡中。 设有背景音乐 有一键通过按钮 等等,块下载去看看吧。
java并发库thread使用,传统线程技术、定时器技术、线程互斥技术,同步通讯技术、多线程共享数据、并发库应用,线程锁技术,阻塞锁、阻塞队列,线程池等应用
第1章 Java开发入门一.填空题1. 面向对象,SUN 2. JavaSE,JavaEE,JavaME3.面向对象、跨平台性、支持多线程4. JDK5.bin
这本书的pdf文件有162M,是最新版高清的pdf,网上原书售价60多元,这里提供的附件是百度云的链接地址。
黑马程序员——Java异步课程源码 plugin Lombok logback.xml 说明 课堂代码主要在 case_java8 子模块内,按章节划分, io.github.hank.java.concurrent.n2 - 同步与异步 io.github.hank.java.concurrent.n3 - Java...
2.适用于黑马程序员Java企业级实战开发《学成在线》微服务项目,基于SpringCloud、SpringCloudAlibaba技术栈开发。 3.采用xxl-job技术。 4.步骤概要: 4.1 作业分片方案 4.2 保证任务不重复执行 4.3 业务流程 5....
title: 黑马JVM学习笔记二 date: 2020-01-13 1:00:00 ...线程是私有的,多线程之间分别有各自的程序计数器记录对应线程的执行位置 程序计数器是Java虚拟机规范中唯一一个不会存在内存溢出的区(堆和栈等会出现内存溢
给大家分享一篇我在学习java过程中...包含常见的面试题:JVM、Java集合、多线程并发、java基础、SSM框架原理、微服务、Netty和RPC、网络、日志、算法、数据结构、加密、分布式算法、机器学习、大数据等知识点,都是干货
第1章 MFC概述 1 1.1 MFC是一个编程框架 1 1.1.1 封装 1 1.1.2 继承 2 1.1.3 虚拟函数和动态约束 2 1.1.4 MFC的宏观框架体系 2 1.2 MDI应用程序的构成 3 1.2.1 构成应用程序的对象 3 1.2.2 构成应用程序的对象之间的...