java中的多线程来看一看基础了
一 引言 :
进程是一个正在执行中的程序,每个进程执行都有一个执行顺序,或执行路径;
线程是进程中的内容,是进程中独立的控制单元;
线程控制着进程的执行,或者是一个控制单元;
一个进程中至少有一个线程;
二 如何创建线程
1.第一种方式为:
将类声明为Thread的子类,该子类应重写Thread类的run方法
例如:
class TestChildThread extends Thread{@Overridepublic void run() {super.run();}
}
创建好子线程后,我们接下来启动使用它
class Test { public static void main(String[] args) {//创建线程TestChildThread d = new TestChildThread(); //启动d . start();}}
2. 第二种方式是实现 Runnable接口,并重写Thread的run方法
class RunnableDemo implements Runnable{@Overridepublic void run() {}
}class TestRunnableClass{public static void main(String[] args){RunnableDemo runnableDemo = new RunnableDemo();Thread t = new Thread(runnableDemo);t . start();}
}
注: 1. 定义类实现Runable接口来创建线程
2. 覆盖 Runable 中run方法,将要执行的代码放入;
3. 通过 Thread 类建立线和对象
4.将 Runnable接口子类对象作为实际参数传递给Thread类的构造函数中
5.调用 Thread类的 start 方法 开户线程
注: 两种创建线程方式的区别:
实现方式的好处,了单继承的局限性
在定义线程时,建议使用实现类
继承Thread: 线程代码存放在Thread类的run方法中
实现Runable,线程将代码存放在接口的子类run方法中
3.注 : 在某一个时刻,只能有一个程序在运行;
在多线程中,有一个特性:随机执行;
d . run();是调用类Demo类中的run方法,而未启动线程
4.为什么要重写run方法?
将自定义代码存储在run方法中,让线程运行;
例:
class ThreadDemos1 extends Thread
{public void run(){for(int x =0;x<10;x++){System.out.println(this.getName()+" " + x);}}
}//其中 this.getName 是获得线程的名称class ThreadDemos2 extends Thread
{ThreadDemos2(String name){super(name);}public void run(){for(int x =0;x<10;x++){System.out.println(this.getName()+" " + x);}}
}
建立测试类
public class TestDemo {public static void main(String[] args) {ThreadDemos1 d1 = new ThreadDemos1();d1.start();ThreadDemos2 d = new ThreadDemos2("one");d.start();}
}
三 多线程运行状态
阻塞状态
|
线程建立——(start())——运行————sleep()————冻结
|
stop
四 自定义线程名称:
** 线程都有自己的名称 : Thread-标号 ,, 标号是从0开始的;
** 获得线程名称的方法 : this.getName(); Thread.currentThread().getName()
** 可以在线程初始化始时对线程命名;
1.在线程初始化时候对其命名
class Demoss extends Thread{public void run(){for(int x =0;x<10;x++){System.out.println(this.getName()+" " + x);}}}public class TestDemo {public static void main(String[] args) {Demoss d1 = new Demoss("one");d1.start();}
}
2. 可以使用构造函数对其重命名;
class Demos extends Thread{Demos(String name){super(name);}public void run(){for(int x =0;x<10;x++){System.out.println(this.getName()+" " + x);}}}public class TestDemo {public static void main(String[] args) {Demos d1 = new Demos("one");d1.start();}
}
五 多线程的安全问题
1.同步 代码块
java对于多线程的安全问题,提供了专业的解决方式,就是 使用同步代码块,
结构
synchronized(对象){被同步的代码}
例如一个售票例子
总共1000张票 四个售票机
package test;public class TestDeoo {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();}}class Ticket implements Runnable{private int tick=1000;Object obj = new Object();public void run(){while(true){synchronized(obj){if(tick>0){" try{Thread.sleep(10);}catch(Exception e){ };} <pre name="code" class="java">
System.out.println(Thread.currentThread().getName()+"sale"+tick--); } } }}
2.同步代码块原理:
例如有两个线程,当线程0获得CPU的执行权后,会读到synchronized代码块, 判断,然后会获得进入许可,继续执行下面的代码,随后synchronized 关闭入口,读到 stop时,线程结束,此时入口开放,等待下一线程的进入执行。。。。。。。。。。
3.使用同步代码块的前提
<1> 必须有两个或者两个以上的线程
<2> 必须是多个线程使用同一个锁
4.同步代码块的好处
解决了线程的安全问题
5.同步代码块的弊端
多个线程要判断锁,较为消耗资源
六 同步函数
例
public class StringDemo {public static void main(String[] args) {Cuss c = new Cuss();Thread t = new Thread(c);Thread t2 = new Thread(c);t.start();t2.start();}
}class Bank {private int sum;Object obj = new Object();public void add(int x) {synchronized (obj) {sum = sum + x;try {Thread.sleep(10);} catch (Exception e) {}System.out.println("sum " + sum);}}
}class Cuss implements Runnable {private Bank b = new Bank();public void run() {for (int x = 0; x < 3; x++) {b.add(100);System.out.println(Thread.currentThread().getName());}}
}
使用同步函数形式来写出上述问题
class Banks {private int sum;Object obj = new Object();public synchronized void add(int x) {sum = sum + x;try {Thread.sleep(10);} catch (Exception e) {}System.out.println("sum " + sum);}
}class Cuss implements Runnable{private Banks b = new Banks();public void run() {for (int x = 0; x < 3; x++) {b.add(100);System.out.println(Thread.currentThread().getName());}}
}public class stringDemo {public static void main(String[] args) {Cuss c = new Cuss();Thread t = new Thread(c);Thread t2 = new Thread(c);t.start();t2.start();}
}
七 单例设计模式
1. 饿汉式
class Single {private static final Single s = new Singles();private Single() {}public static Single getInstanceP{return s;}
}
2. 懒汉式
class Single {private static Single s = null;private Single() {}public static Single getInstance() {if (s == null) {synchronized (Single.class) {if (s == null) {s = new Single();}}}return s;}
}
线程间的通讯
线程间的的通讯,其实就是多个线程在操作同一个资源;但是操作的动作不同的资源
新建一个资源:
class Res
{String name;String sex; }
创建一个输入线程类: 输入与输出线程要操作同一个资源
class Input implements Runnable
{Res r;Input(Res r){this.r=r;}public void run(){boolean b =true;while(true){if(b){r.name="lishi";r.sex="man";b = false;}else{r.name="李四";r.sex="男";b = true;}}}
}
新建一个输出线程: 输入线程与输出线程操作的是同一个资源
class Output implements Runnable
{Res r;Output(Res r){this.r=r;}public void run(){while(true){System.out.println(r.name);}}
}
新建一个测试类
public class TestDemo {public static void main(String[] args) {Res r = new Res();Input in = new Input(r);Output out = new Output(r);Thread t = new Thread(in );Thread tl = new Thread(out);t.start();tl.start();}
}
这个程序的输出结果应该为 lishi man
李四 男
。。。。。
测试一下,会出现乱码现象,如果要修改安全问题,就应该使用同步代码块
class Res
{String name;String sex; }
class Input implements Runnable
{Res r;Input(Res r){this.r=r;}public void run(){boolean b =true;while(true){synchronized(r){if(b){r.name="lishi";r.sex="man";b = false;}else{r.name="李四";r.sex="男";b = true;}}}}
}
class Output implements Runnable
{Res r;Output(Res r){this.r=r;}public void run(){synchronized(r){while(true){System.out.println(r.name+" "+r.sex);}}}
}
这样的话就解决了线程间的安全问题了
线程间的等待唤醒机制
新建一个资源
class Res
{String name;String sex; boolean bo = false;}
class Input implements Runnable
{Res r;Input(Res r){this.r=r;}public void run(){boolean b =true;while(true){synchronized(r){if(r.bo)try{r.wait();}catch(Exception e){}if(b){r.name="lishi";r.sex="man";b = false;}else{r.name="李四";r.sex="男";b = true;}r.bo =true ; r.notify();}}}
}
class Output implements Runnable
{Res r;Output(Res r){this.r=r;}public void run(){while(true){synchronized(r){if(!r.bo)try{r.wait();}catch(Exception e){}System.out.println(r.name+" "+r.sex);r.bo=false;r.notify();}}}
}
public class StringDemo {public static void main(String[] args) {Res r = new Res();Input in = new Input(r);Output out = new Output(r);Thread t = new Thread(in );Thread tl = new Thread(out);t.start();tl.start();}
}
输出结果为
李四 男
lishi man
李四 男
lishi man
李四 男
lishi man
李四 男
lishi man
李四 男
lishi man
李四 男
lishi man
李四 男
lishi man
李四 男
lishi man
李四 男
注 : wait :
notify()
notifyAll()
都使用在同步中,因为要对持有监视器的线程操作,所以要使用在同步中,因为只有 同步才具有锁;
为什么这些操作线程的方法要定义在object 类中呢?
因为这些方法在操作同步线程中,都必须要标识它们所操作线程的锁,只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒,也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中
优化后的代码
public class TestDemo {public static void main(String[] args) {Resi r = new Resi();new Thread(new Inputi(r)).start();new Thread(new Outputi(r)).start();}
}
class Resi
{String name;String sex; boolean bo = false;public synchronized void set(String name ,String sex){if(bo)try{this.wait();}catch(Exception e){}this.name = name;this.sex = sex;bo = true ;this.notify();}public synchronized void out(){if(!bo)try{this.wait();}catch(Exception e){}System.out.println(name +" "+sex);bo = false;this.notify();}
}class Inputi implements Runnable
{Resi r;Inputi(Resi r){this.r = r;}public void run(){boolean b =true;while(true){if(b){r.set("lishi","man");b = false;}else{r.set("李四","男");b = true;}}}
}class Outputi implements Runnable
{Resi r;Outputi(Resi r){this.r = r;}public void run(){while(true)r.out();}
生产者与消费者 线程间的通信
public class StringDemo {public static void main(String[] args) {Resourced r = new Resourced();new Thread(new Producerd(r)).start();//1new Thread(new Producerd(r)).start();//2new Thread(new Consumerd(r)).start();//3new Thread(new Consumerd(r)).start();//4}
}
/** 生产一个,消费一个*/
class Resourced
{private String name;private int count = 1;private boolean flag = false;public synchronized void set(String name){while(flag)try{wait();}catch(Exception e){}this.name = name+" "+count++;System.out.println(Thread.currentThread().getName()+"生产者,,,," + this.name);flag = true;this.notifyAll();}public void out(){while(!flag)try{wait();}catch(Exception e){}System.out.println(Thread.currentThread().getName()+"消费者 " + this.name);flag = false;this.notifyAll();}}
class Producerd implements Runnable
{private Resourced res ;Producerd(Resourced res){this.res = res;}public void run(){while(true)'7Bres.set("商品");}}
}
class Consumerd implements Runnable
{private Resourced res;Consumerd(Resourced res){this.res = res;}public void run(){while(true){res.out();}}
}
java中的多线程来看一看基础了相关推荐
- Java 中的多线程你只要看这一篇就够了
作者丨纳达丶无忌 https://www.jianshu.com/p/40d4c7aebd66 引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多 ...
- Java中的多线程你只要看这一篇就够了
如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...
- Java基础——深入理解Java中的多线程(超级详细,值得你看)
Java中的多线程 进程(process)是程序的一次执行过程,或是正在运行的有一个程序,或是正在运行的一个程序.是一个动态的过程:有它自身的产生.存在和消亡的过程.--生命周期. 线程(thread ...
- 草根方式学习java中的多线程
草根方式学习java中的多线程 下面有具体的代码和截图 源码点这里 多线程即在同一时间,可以做多件事情(说白了,就是齐头并进) 单线程就是按部就班 创建多线程有2种方式,分别是继承线程Thread类, ...
- Java中的多线程编程(超详细总结)
文章目录 Java中的多线程编程(超详细总结) 一.线程与多线程的概念 二.线程与进程之间的关系 三.一个线程的生命周期 四.多线程的目的和意义 五.线程的实现的方式 Java中的多线程编程(超详细总 ...
- JAVA中的多线程(一)
JAVA中的多线程(一) 进程:是一个正在执行中的程序 每一个进程执行都有一个执行的顺序,该顺序是一个执行路径,或者叫控制单元 线程:就是进程中的一个独立的控制单元 线程在控制着进程的执行 一个进程中 ...
- Java中控制多线程顺序执行
Java中控制多线程顺序执行 一.概述 二.普通示例 三.控制示例 3.1.设置线程优先级 3.2.使用线程类的join() 3.2.1.在主线程join() 3.2.2.在子线程join() 3.3 ...
- JAVA中的多线程(八):线程的优先级和yield方法
JAVA中的多线程(八):线程的优先级和yield方法 优先级代表着抢资源的频率 所有线程默认优先级是5 yield()临时释放线程的执行权 1 class Demo implements Runna ...
- JAVA中的多线程与运动仿真(1)——用JAVA来放一场烟花
JAVA中的多线程与运动仿真(1)--用JAVA来放一场烟花 一.实现效果的简单展示: 初步实现的动态效果为在鼠标点击之后,点击之处出现一簇小球,然后向不同方向散开变大. 利用这一效果,再在后续增加颜 ...
最新文章
- C#筛法求出范围内的所有质数
- 计算机系统结构sw指令集,《深入理解计算机系统》第三章学习笔记
- ajax xmlhttp.responsetext,Ajax:xmlhttp.responseText响应显示完整的内部HTML而不是关闭所需文本...
- 七十八、SpringBoot监听rabbitmq和创建交换器,队列
- 【PAT甲级 十进制转十三进制】1027 Colors in Mars (20 分) Java版 5/5通过
- 无废话WPF系列5:控件派生图
- 如何变得有价值,需要突破问题,提高解决各种问题的能力?
- oracle仲裁机制,仲裁逻辑设计要点
- easyUI datagrid 重复发送URL请求
- Linux ---yum源详解
- 收藏!深度学习必读10篇经典算法论文总结!
- python制作一个简易计算器_最简易的python计算器实现源代码
- 软件工程导论患者监护系统
- 关于数字化营销,这些知识点你一定要知道
- 公式计算机实现,数学公式的计算机表达(精选).doc
- 第二工业大学计算机应用大专录取分,上海第二工业大学2017年分省分专业录取分数线...
- Verilog加法器设计
- 解决安装 ISE14.7 Windows10 时出错
- 企业——nginx的图片压缩、https模块、重写规则、盗链
- Cannot open D:\Anaconda3\Scripts\pip-script.py 解决
热门文章
- ThunderNet:国防科大、旷视提出首个在ARM上实时运行的通用目标检测算法
- OpenCV手部关键点检测(手势识别)代码示例
- js添加关闭功能_微信小程序开发之添加夜间模式功能
- 639 页《深度学习:Deep Learning》硬核课程 PPT 下载
- 中国科学院计算机网络信息中心怀柔分中心,计算机网络信息中心怀柔分中心(二期)建设项目荣获2018年度“北京市安装工程优质奖”...
- 机器学习实战 | 数据探索(变量变换、生成)
- 专业工程师看过来~ | RDD、DataFrame和DataSet的细致区别
- tensorflow 特征预处理总结
- 在GIS中运用坐标系统
- 如何显示python的内置模块_python之模块(内置模块)