JAVA 11(多线程)

线程间通信,其实就是多个线程在操作同一个资源,但操作动作不同。

同步代码块用了同一个锁。

public class Test

{

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();

}

}

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="mike";

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)

{

synchronized(r)

{

System.out.println(r.name+"....."+r.sex);

}

}

}

}

改代码 会打印重复的 同一个人,利用线程直接的通信修改,在Res中给一个标记。

等待唤醒机制

 

 

非静态同步函数用的锁时this。

静态同步函数用的锁时 类名.class。

同步代码块用的锁任意。自己设置的

wait()   :格式 try{} catch() {}

notify()

notifyAll()

三个方法都继承于Object类,后两个方法必须有对象的监视器才可以使用(也就是同步中的锁,必须在同步中才可以使用)

都使用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有在同步中,才有锁。

为什么操作线程的方法要定义在Object中呢,因为这些方法在操作同步中的线程时,都必须要标示他们所操作线程持有的锁,只有同一个锁上的被等待线程可以被同一个锁上notify()唤醒,不可以对不同所中的线程进行唤醒

也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在Obj类中。

public class Test

{

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();

}

}

class Res

{

String name;

String sex;

boolean flag = 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.flag)

try

{

r.wait();

}

catch(Exception e)

{

}

if(b)

{

r.name="mike";

r.sex="man";

b=false;

}

else

{

r.name="丽丽";

r.sex="女女女女";

b=true;

}

r.flag=true;

r.notify();

}

}

}

}

class Output implements Runnable

{

Res r;

Output(Res r)

{

this.r=r;

}

public void run()

{

while(true)

{

synchronized(r)

{

if(!r.flag)

try

{

r.wait();

}

catch(Exception e)

{

}

System.out.println(r.name+"....."+r.sex);

r.flag=false;

r.notify();

}

}

}

}

继续举例:

多个线程负责生产,多个线程负责消费。注意notifyAll 和while(flag)

对于多个生产者和消费者。

为什么要定义while判断标记?

让被唤醒的线程再一次判断标记。

为什么要定义notifyAll

因为需要唤醒对方线程。

因为只用notify的话,容易出只唤醒本方线程的情况,导致程序中所有线程都等待。

public class Test

{

public static void main(String args [])

{

Resource r = new Resource();

Producer pro = new Producer(r);

Consumer con = new Consumer(r);

Thread t1 = new Thread(pro);

Thread t2 = new Thread(con);

Thread t3 = new Thread(pro);

Thread t4 = new Thread(con);

t1.start();

t2.start();

t3.start();

t4.start();

}

}

class Resource

{

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 synchronized void out()

{

while(!flag)

try

{

wait();

}

catch(Exception e)

{

}

System.out.println(Thread.currentThread().getName()+"...消费者......."+this.name);

flag = false;

this.notifyAll();

}

}

class Producer implements Runnable

{

private Resource res;

public void run()

{

while(true)

{

res.set("+商品+");

}

}

Producer(Resource res)

{

this.res=res;

}

}

class Consumer implements Runnable

{

private Resource res;

public void run()

{

while(true)

{

res.out();

}

}

Consumer(Resource res)

{

this.res=res;

}

}

jdk5升级之后

 

java.util.concurrent.locks 接口

jdk1.5中提供了多线程的升级解决方案,将同步的Synchronized 替换成Lock操作,将Object中的wait,notify,nofityAll替换成立Condition对象,该对象可以Lock锁,进行获取。一个锁可以对应多个Condition。

JDK1.5 中提供了多线程升级解决方案。

将同步Synchronized替换成现实Lock操作。

将Object中的wait,notify notifyAll,替换了Condition对象。

该对象可以Lock锁 进行获取。

该示例中,实现了本方只唤醒对方操作。

Lock:替代了Synchronized

lock

unlock

new Condition()

Condition:替代了Object wait notify notifyAll

await();

signal();

signalAll();

在该实力中,实现了本方只唤醒对方的操作。

更改之后的代码:

import java.util.concurrent.locks.*;

class Test

{

public static void main(String[] args)

{

Resource r = new Resource();

Producer pro = new Producer(r);

Consumer con = new Consumer(r);

Thread t1 = new Thread(pro);

Thread t2 = new Thread(pro);

Thread t3 = new Thread(con);

Thread t4 = new Thread(con);

t1.start();

t2.start();

t3.start();

t4.start();

}

}

/*

JDK1.5 中提供了多线程升级解决方案。

将同步Synchronized替换成现实Lock操作。

将Object中的wait,notify notifyAll,替换了Condition对象。

该对象可以Lock锁 进行获取。

该示例中,实现了本方只唤醒对方操作。

Lock:替代了Synchronized

lock

unlock

newCondition()

Condition:替代了Object wait notify notifyAll

await();

signal();

signalAll();

*/

class Resource

{

private String name;

private int count = 1;

private boolean flag = false;

//  t1    t2

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();

}

}

}

class Producer implements Runnable

{

private Resource res;

Producer(Resource res)

{

this.res = res;

}

public void run()

{

while(true)

{

try

{

res.set("+商品+");

}

catch (InterruptedException e)

{

}

}

}

}

class Consumer implements Runnable

{

private Resource res;

Consumer(Resource res)

{

this.res = res;

}

public void run()

{

while(true)

{

try

{

res.out();

}

catch (InterruptedException e)

{

}

}

}

}

停止线程

 

停止线程的原理

只有一种方法,就是run()方法结束

线程.interrupt  //强制唤醒

stop方法已经过时。

如何停止线程?

只有一种,run方法结束。

开启多线程运行,运行代码通常是循环结构。

只要控制住循环,就可以让run方法结束,也就是线程结束。

特殊情况:

当线程处于了冻结状态。

就不会读取到标记。那么线程就不会结束。

当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。

强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

Thread类提供该方法 interrupt();

设置为守护线程,当其他线程都结束后,并且只剩下守护线程,守护线程自动结束

而且必须早start()之前设置守护线程

join方法

t1.join(); 抢夺cpu执行权,当t1执行结束的时候,主线程才解冻。

join:

当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。

join可以用来临时加入线程执行。

线程的优先级

 

 

自己写的代码:

import java.util.concurrent.locks.*;

import java.util.concurrent.locks.Lock.*;

public class Test

{

public static void main(String args[])

{

Resource r = new Resource();

Pro p = new Pro(r);

Cro c = new Cro(r);

Thread t1 = new Thread(p);

Thread t2 = new Thread(p);

Thread t3 = new Thread(c);

Thread t4 = new Thread(c);

t1.start();

t2.start();

t3.start();

t4.start();

}

}

class Resource

{

private boolean flag = false;

private int count = 1;

private Lock lock = new ReentrantLock();

private Condition con_pro = lock.newCondition();

private Condition con_con = lock.newCondition();

public void set()

{

lock.lock();

try {

while(flag)

con_pro.await();

count++;

System.out.println(Thread.currentThread().getName()+"生产了第"+count+"张票");

flag=true;

con_con.signal();

} catch (InterruptedException e) {

}

finally

{

lock.unlock();

}

}

public void hua()

{

lock.lock();

try {

while(!flag)

con_con.await();

System.out.println(Thread.currentThread().getName()+"消费了第"+count+"张票***");

flag=false;

con_pro.signal();

} catch (InterruptedException e) {

}

finally

{

lock.unlock();

}

}

}

class Pro implements Runnable

{

Resource r;

Pro(Resource r)

{

this.r=r;

}

public void run()

{

while(true)

r.set();

}

}

class Cro implements Runnable

{

Resource r;

Cro(Resource r)

{

this.r=r;

}

public void run()

{

while(true)

r.hua();

}

}

时间: 2024-11-11 06:35:08

JAVA 11(多线程)的相关文章

Java基础--多线程的方方面面

1,什么是线程?线程和进程的区别是什么? 2,什么是多线程?为什么设计多线程? 3,Java种多线程的实现方式是什么?有什么区别? 4,线程的状态控制有哪些方法? 5,线程安全.死锁和生产者--消费者 6,线程的优化有哪些方法? 1,什么是线程?线程和进程的区别是什么? 线程是程序执行的最小单元. 区别: 进程是操作系统进行资源处理和分配的最小单位,而一个进程可以包含多个线程,并共享进程的资源. 2,什么是多线程?为什么设计多线程? 介绍之前,我们需要理解并行和并发的定义: 并行:同一个时刻有多

Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)

一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专家又往往建议我们远离它.比如Thread这个很基础的类,其中很重要的线程状态字段,就是用volatile来修饰,见代码 /* Java thread status for tools, * initialized to indicate thread 'not yet started' */   p

Java入门——多线程(二)

Java入门——多线程(二) 线程的状态 要想实现多线程,必须在主线程中创建新的线程对象.任何线程一般具有5种状态. 创建状态:用构造方法创建一个线程对象之后,新的线程就处于该状态.已经有了相应的内存空间和其他资源和其他资源. 就绪状态:线程进入线程队列排队,等待CPU服务. 运行状态:CPU处理,自动调用run()方法. 阻塞状态:就是在执行过程中暂时挂起.原因有:人为挂起,CPU的决定,sleep(),suspend(),wait()等方法.只有当引起阻塞的原因被消除后,线程才能转入就绪状态

Java基础-多线程-③多线程的同步之synchronized

使用线程同步解决多线程安全问题 上一篇 Java基础-多线程-②多线程的安全问题 中我们说到多线程可能引发的安全问题,原因在于多个线程共享了数据,且一个线程在操作(多为写操作)数据的过程中,另一个线程也对数据进行了操作,从而导致数据出错.由此我们想到一个解决的思路:将操作共享数据的代码行作为一个整体,同一时间只允许一个线程执行,执行过程中其他线程不能参与执行.线程同步就是用来实现这样的机制. synchronized代码块 Java中提供了synchronized关键字,将可能引发安全问题的代码

Java基础-多线程-②多线程的安全问题

什么是线程的安全问题? 上一篇 Java基础-多线程-①线程的创建和启动 我们说使用实现Runnable接口的方式来创建线程,可以实现多个线程共享资源: 1 class Dog implements Runnable { 2 // 定义线程共享数据 3 private int t = 100; 4 5 @Override 6 public void run() { 7 // TODO:死循环,暂不处理 8 while (true) { 9 if (t > 0) { 10 11 System.ou

Java的多线程 简单入门

Java的多线程 简单入门 首先可以先搞清楚什么是程序.进程.线程,以及它们之间的关系: 定义: 一 程序只是一组指令的有序集合,它是静态的 二 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位: 三 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),一个线程可以创建和撤销另一个线程: 进程与线程区别与联系 (

黑马程序员–Java之多线程09

黑马程序员–Java之多线程09 一.线程和进程 在Java中,并发机制非常重要,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程.多线程就是指一个应用程序中有多条并发执行的线索,每条线索都被称作一个线程,它们会交替执行,彼此间可以进行通信.多线程是非常复杂的机制,在每个操作系统中的运行方式也存在差异,window操作系统是多任务操作系统,它以进程为单位.一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程,也就是正在执行的程序.系统

Java的多线程机制:缓存一致性和CAS

Java的多线程机制:缓存一致性和CAS 一.总线锁定和缓存一致性 这是两个操作系统层面的概念.随着多核时代的到来,并发操作已经成了很正常的现象,操作系统必须要有一些机制和原语,以保证某些基本操作的原子性,比如处理器需要保证读一个字节或写一个字节是原子的,那么它是如何实现的呢?有两种机制:总线锁定和缓存一致性. 我们知道,CPU和物理内存之间的通信速度远慢于CPU的处理速度,所以CPU有自己的内部缓存,根据一些规则将内存中的数据读取到内部缓存中来,以加快频繁读取的速度.我们假设在一台PC上只有一

Java入门——多线程(一)

Java入门——多线程(一) 进程与线程的区别 进程是程序的一次动态的执行的过程,需要经历从代码的加载,代码执行到执行完毕的一个完整过程,这个过程也是进程重产生,发展到最终消亡的过程.多进程操作系统利用CPU的分时机制,分时段执行不同程序,由于CPU运行速度非常快,所以就想是多个进程同时运行一样. 线程是比进程更小的执行单位,线程在进程的基础之上进行的进一步划分.所谓多线程是指在一个进程在执行过程中可以产生多个更小的程序单元,这些更小的单元成为线程,可以同时存在,同时运行. 所谓的线程是程序的运

java之多线程(Thread)

1 package DEMO; 2 //主线程 3 public class Example12_2 { 4 public static void main(String [] args ) 5 { 6 Thread mydad ; //用Thread声明线程 7 Thread mymom ; 8 baba ba ; //ba是目标对象 9 mom ma ; 10 ba = new baba(); //创建目标对象 11 ma = new mom(); 12 mydad = new Thread