------- android培训、java培训、期待与您交流! ----------
多线程
线程间通信
其实就是多个线程在操作同一个资源,
但是操作的动作不同。
示意图
例子
class Res{
String name;
String sex;
boolean flag = false;
int x=0;
public synchronized void set(){
if(flag)
try{this.wait();}catch(Exception e){}
if(x==0){
this.name = "mike";
this.sex = "man";
}
else
{
this.name="丽丽";
this.sex="女女";
}
x = (x+1)%2;
this.flag = true;
this.notify();
}
public synchronized void get(){
if(!this.flag)
try{this.wait();}catch(Exception e){}
System.out.println(this.name+"..."+this.sex);
this.flag = false;
this.notify();
}
}
class Input implements Runnable{
private Res r;
Input(Res r){
this.r = r;
}
public void run(){
while(true){
r.set();
}
}
}
class Output implements Runnable{
private Res r;
Output(Res r){
this.r = r;
}
public void run(){
while(true){
r.get();
}
}
}
public class InputOutDemo {
public static void main(String[] args) {
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
在上面的代码中线程t1和t2,一个在添加姓名和性别,而另一个是在打印姓名和性别。添加时按照一个男一个女的顺序添加。并且保证添加一个打印一个。
上面的代码就是线程间通讯的一个例子。一个线程负责添加,另一个线程负责打印添加的内容。在代码中分别将信息添加方法set()和信息打印方法get()加锁,成为同步函数。两个方法使用的是同一个锁,这就保证了,当有一个线程在对信息进行操作时(包括添加和打印),其他的线程无法计入同步函数,这样就保证了安全,不会打印出错误信息。
同步中的方法
wait(): 在其他线程调用此对象的notify() 方法或 notifyAll()方法前,导致当前线程等待。此时线程将释放cpu执行权,并且释放锁,此时其它锁可以进入此同步中。
notify():
唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个wait()方法,在对象的监视器上等待。
简单理解为可唤醒已经失去cpu执行权的线程,使之获得cpu执行资格,当然该线程不一定马上
就会得到cpu执行权,这还要排队等前面的线程释放cpu执行权。另外此方法会优先唤醒,处于同一同步代码中的线程。
notifyAll():
唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个wait方法,在对象的监视器上等待。与notify作用类似。区别在于,它会无差别的唤醒所有等待线程,不会区分是否在同一同步代码中。
sleep(long millis):
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。
此方法不是同步中特有的,此方法将释放cpu执行权,而不会释放锁。也就是说在同步中,即使线程处于sleep()的状态中,其他线程也进来不了,因为锁没有释放。
注意:wait(),notify(),notifyAll(),方法只能在同步中,否则代码运行时会抛出非法监视异常。
Lock接口
JDK1.5 中提供了多线程升级解决方案。将同步Synchronized替换成实现Lock操作。
产生原因
synchronized可以解决同步中的安全问题,但是也存在一些不足
synchronized方法和代码块,会隐式的为进入这些代码的线程加锁,但代码中有多层锁时,线程
就会依次加上这些锁,并且要按照相反的顺序去释放这些锁,只有在退出相应代码时锁才会被
释放。这种方式太呆板,当需要在同步代码A中释放同步B中的锁定,这种方式就无能为力了。
此时我们需要一种更加灵活的方式来处理同步问题,Lock技术就依次产生。Lock技术可提供比synchronized更广泛的操作,下面只介绍与synchronized相关内容。
Lock与synchronized的关系
1,将synchronized 替换成了Lock接口。
将隐式锁,升级成了显示锁。
Lock中的方法
获取锁:lock();
放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获释取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。
和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立wait和notify方法。
现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个Lock锁上可以有多 个Condition对象。
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();//t1,t2
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();
}
finally
{
lock.unlock();//释放锁的动作一定要执行。
}
}
// t3 t4
public void out()throws InterruptedException
{
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
condition_pro.signal();
}
finally
{
lock.unlock();
}
}
}
注意lock.unlock()一定要执行,即使发生异常锁得到释放,以便其它线程进入。
线程停止
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。
只要控制住循环,就可以让run方法结束,也就是线程结束。
class StopThread implements Runnable{
private boolean flag = true;
public synchronized void run(){
while(flag)
{
System.out.println(Thread.currentThread().getName()+"..run");
}
}
public void changeFlag()
{
flag = false;
}
}
public class StopThreadDemo {
public static void main(String[] args) {
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
int num=0;
while(true){
if(num++==60){
//此时改变标记,flag为false,run方法中的循环结束,线程t1,t2也结束
st.changeFlag();
break;
}
System.out.println(Thread.currentThread().getName()+"..."+num);
}
System.out.println("over");
}
}
特殊情况:
当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
需要强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
Thread类提供该方法 interrupt();
class StopThread implements Runnable{
private boolean flag = true;
public synchronized void run(){
while(flag)
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println(Thread.currentThread().getName()+"..Exception");
//如果不在此处更改标记,下一次循环,线程又将进入冻结状态
flag = false;
}
System.out.println(Thread.currentThread().getName()+"..run");
}
}
public void changeFlag()
{
flag = false;
}
}
public class StopThreadDemo {
public static void main(String[] args) {
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
int num=0;
while(true){
if(num++==60){
t1.interrupt();//使线程从冻结状态中恢复过来,此时线程会抛出InterruptedException异常
t2.interrupt();
//st.changeFlag();调用此方法不能保证在线程t1和t2进行标记判断前,标记已更改。
break;
}
System.out.println(Thread.currentThread().getName()+"..."+num);
}
System.out.println("over");
}
}
线程中的其它方法
join
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
class Demo implements Runnable{
public void run()
{
for(int x=0;x<100;x++){
System.out.println(Thread.currentThread().toString()+".."+x);
// Thread.yield();
}
}
}
public class JoinDemo {
public static void main(String[] args) throws InterruptedException {
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
// t1.setPriority(Thread.MAX_PRIORITY);
t1.join();
t2.start();
for(int i=0;i<40;i++){
System.out.println(Thread.currentThread().getName()+".."+i);
}
}
}
可见当线程t1,执行完成后,才开始接着执行主线程。
setDaemon
将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
也就是说,主线程结束时,此线程也会结束,该方法必须在启动线程前调用。
yield
暂停当前正在执行的线程对象,并执行其他线程。
setPriority
更改线程的优先级,优先级范围1-10,api中已定义好了几个常量
MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY。
t.setPriority(MAX_PRIORITY)线程t被设置为最大优先级。
相关推荐
黑马程序员_张孝祥_Java多线程与并发库,视频+代码+资料
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
NULL 博文链接:https://huangminwen.iteye.com/blog/1157983
1、 面向对象、跨平台性、健壮性、安全性、可移植性、多线程性、动态性等。 2、 JRE(Java Runtime Environment,Java 运行时环境),它相当于操作系统部分,提供了 Java 程序运 行时所需要的基本条件和许多 Java ...
当一个进程中线程有多个时,是多线程。 为什么要用多线程 1,让计算机"同时"做多件事情,节约时间。 2,后台运行程序,提高程序的运行效率.。 3,多线程可以让程序"同时"处理多个事情。 4,...
这是一个java写的拼图游戏,用了swing、多线程等知识,可以设置行数列、列数、还有使用多线程写的游戏动画,拼图的图块具有磁贴设计,代码封装性较强,容易移植,纯原创。
java并发库thread使用,传统线程技术、定时器技术、线程互斥技术,同步通讯技术、多线程共享数据、并发库应用,线程锁技术,阻塞锁、阻塞队列,线程池等应用
java.util.concurrent包、synchronized关键字、Swing框架、Java内存模型等内容也均有涉及,不仅能够了解Java多线程的相关知识,还可加深对Java语言的理解。 本书适合以下读者阅读 a.对多线程感兴趣的人 b.对Java...
传智播客_Java培训_毕向东_Java基础[05-多线程]系黑马程序员_毕向东_Java基础视频教程
264张图表 + 300段Java示例程序 = 轻松学习多线程编程 日本经典多线程入门书,原版长销11年! 本书适合以下读者阅读 a.对多线程感兴趣的人 b.对Java编程感兴趣的人 c.对设计模式感兴趣的人 d.对面向对象开发感兴趣的...
第1章 Java开发入门一.填空题1. 面向对象,SUN 2. JavaSE,JavaEE,JavaME3.面向对象、跨平台性、支持多线程4. JDK5.bin
|--利用FinalHttp实现多线程断点续传 |--加密之MD5 |--动画Animation详解 |--动画之view左右抖动 |--动画之移动动画 |--动画之组合动画 |--动画之缩放动画ScaleAnimation |--反序列化对象 |--发送短信 读天气 调音量...
萌新做的一个简单的Java拼图游戏 启动类:pers.sept.jigsaw1.swing下的...多线程。 下拉列表选择数字可以切换关卡图片,最后的“+”,可以添自己的图片到关卡中。 设有背景音乐 有一键通过按钮 等等,块下载去看看吧。
这本书的pdf文件有162M,是最新版高清的pdf,网上原书售价60多元,这里提供的附件是百度云的链接地址。
给大家分享一篇我在学习java过程中...包含常见的面试题:JVM、Java集合、多线程并发、java基础、SSM框架原理、微服务、Netty和RPC、网络、日志、算法、数据结构、加密、分布式算法、机器学习、大数据等知识点,都是干货
2.适用于黑马程序员Java企业级实战开发《学成在线》微服务项目,基于SpringCloud、SpringCloudAlibaba技术栈开发。 3.采用xxl-job技术。 4.步骤概要: 4.1 作业分片方案 4.2 保证任务不重复执行 4.3 业务流程 5....
黑马程序员——Java异步课程源码 plugin Lombok logback.xml 说明 课堂代码主要在 case_java8 子模块内,按章节划分, io.github.hank.java.concurrent.n2 - 同步与异步 io.github.hank.java.concurrent.n3 - Java...
title: 黑马JVM学习笔记二 date: 2020-01-13 1:00:00 ...线程是私有的,多线程之间分别有各自的程序计数器记录对应线程的执行位置 程序计数器是Java虚拟机规范中唯一一个不会存在内存溢出的区(堆和栈等会出现内存溢
Java基础笔记分为 Java基础篇 和 Java加强篇 Java基础篇包括: 1. Java环境搭建、Java快速入门、IDEA开发工具 ...11. 多线程 12. 网络编程 13. 单元测试、反射、注解、动态代理 14. XML、解析、工厂模式和装饰模式
多线程支持: Java内置了对多线程的支持,允许程序同时执行多个任务。这对于开发需要高并发性能的应用程序(如服务器端应用、网络应用等)非常重要。 自动内存管理(垃圾回收): Java具有自动内存管理机制,通过...