《Java多线程编程核心技术》读后感(十)
一生产一消费:操作栈
本实例是使生产者向堆栈List对象中放入数据,使消费者从List堆栈中取出数据。List最大容量是1
package Third; import java.util.ArrayList;
import java.util.List; public class MyStack {
private List list = new ArrayList(); synchronized public void push() {
try {
if (list.size() == 1) {
this.wait();
}
list.add("anyString=" + Math.random());
this.notify();
System.out.println("push=" + list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public String pop() {
String returnValue = "";
try {
if (list.size() == 0) {
System.out.println("pop操作中的:"
+ Thread.currentThread().getName() + " 线程呈wait状态");
this.wait();
}
returnValue = "" + list.get(0);
list.remove(0);
this.notify();
System.out.println("pop=" + list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
return returnValue;
}
}
package Third;
public class P_Thread extends Thread {
private P p;
public P_Thread(P p) {
super();
this.p = p;
}
@Override
public void run() {
while (true) {
p.pushService();
}
}
}
package Third;
public class C_Thread extends Thread {
private C r;
public C_Thread(C r) {
super();
this.r = r;
}
@Override
public void run() {
while (true) {
r.popService();
}
}
}
package Third;
public class P {
private MyStack myStack;
public P(MyStack myStack) {
super();
this.myStack = myStack;
}
public void pushService() {
myStack.push();
}
}
package Third;
public class C {
private MyStack myStack;
public C(MyStack myStack) {
super();
this.myStack = myStack;
}
public void popService() {
System.out.println("pop=" + myStack.pop());
}
}
package Third;
public class Run {
public static void main(String[] args) {
MyStack myStack = new MyStack();
P p = new P(myStack);
C r = new C(myStack);
P_Thread pThread = new P_Thread(p);
C_Thread rThread = new C_Thread(r);
pThread.start();
rThread.start();
}
}

程序运行的结果是size()不会大于1
一生产多消费-操作栈:解决wait条件改变与假死
上述代码只需要更改run.java
package Third;
public class Run {
public static void main(String[] args) throws InterruptedException {
MyStack myStack = new MyStack();
P p = new P(myStack);
C r1 = new C(myStack);
C r2 = new C(myStack);
C r3 = new C(myStack);
C r4 = new C(myStack);
C r5 = new C(myStack);
P_Thread pThread = new P_Thread(p);
pThread.start();
C_Thread cThread1 = new C_Thread(r1);
C_Thread cThread2 = new C_Thread(r2);
C_Thread cThread3 = new C_Thread(r3);
C_Thread cThread4 = new C_Thread(r4);
C_Thread cThread5 = new C_Thread(r5);
cThread1.start();
cThread2.start();
cThread3.start();
cThread4.start();
cThread5.start();
}
}

问题的出现是因为在Mystack.java类中使用了if语句作为条件判断。因为条件发生改变时并没有及时的相应,所以多个呈wait状态的线程被唤醒,继而执行list.remove(0)代码而出现异常。解决这个办法是,将if改成while
package Third; import java.util.ArrayList;
import java.util.List; public class MyStack {
private List list = new ArrayList(); synchronized public void push() {
try {
while (list.size() == 1) {
this.wait();
}
list.add("anyString=" + Math.random());
this.notify();
System.out.println("push=" + list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public String pop() {
String returnValue = "";
try {
while (list.size() == 0) {
System.out.println("pop操作中的:"
+ Thread.currentThread().getName() + " 线程呈wait状态");
this.wait();
}
returnValue = "" + list.get(0);
list.remove(0);
this.notify();
System.out.println("pop=" + list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
return returnValue;
}
}

出现了假死状态,解决办法是notifyAll()

多生产与一消费:操作栈
package Third;
public class Run {
public static void main(String[] args) throws InterruptedException {
MyStack myStack = new MyStack();
P p1 = new P(myStack);
P p2 = new P(myStack);
P p3 = new P(myStack);
P p4 = new P(myStack);
P p5 = new P(myStack);
P p6 = new P(myStack);
P_Thread pThread1 = new P_Thread(p1);
P_Thread pThread2 = new P_Thread(p2);
P_Thread pThread3 = new P_Thread(p3);
P_Thread pThread4 = new P_Thread(p4);
P_Thread pThread5 = new P_Thread(p5);
P_Thread pThread6 = new P_Thread(p6);
pThread1.start();
pThread2.start();
pThread3.start();
pThread4.start();
pThread5.start();
pThread6.start();
C c1 = new C(myStack);
C_Thread cThread = new C_Thread(c1);
cThread.start();
}
}

多生产与多消费:操作栈
package Third;
public class Run {
public static void main(String[] args) throws InterruptedException {
MyStack myStack = new MyStack();
P p1 = new P(myStack);
P p2 = new P(myStack);
P p3 = new P(myStack);
P p4 = new P(myStack);
P p5 = new P(myStack);
P p6 = new P(myStack);
P_Thread pThread1 = new P_Thread(p1);
P_Thread pThread2 = new P_Thread(p2);
P_Thread pThread3 = new P_Thread(p3);
P_Thread pThread4 = new P_Thread(p4);
P_Thread pThread5 = new P_Thread(p5);
P_Thread pThread6 = new P_Thread(p6);
pThread1.start();
pThread2.start();
pThread3.start();
pThread4.start();
pThread5.start();
pThread6.start();
C r1 = new C(myStack);
C r2 = new C(myStack);
C r3 = new C(myStack);
C r4 = new C(myStack);
C r5 = new C(myStack);
C r6 = new C(myStack);
C r7 = new C(myStack);
C r8 = new C(myStack);
C_Thread cThread1 = new C_Thread(r1);
C_Thread cThread2 = new C_Thread(r2);
C_Thread cThread3 = new C_Thread(r3);
C_Thread cThread4 = new C_Thread(r4);
C_Thread cThread5 = new C_Thread(r5);
C_Thread cThread6 = new C_Thread(r6);
C_Thread cThread7 = new C_Thread(r7);
C_Thread cThread8 = new C_Thread(r8);
cThread1.start();
cThread2.start();
cThread3.start();
cThread4.start();
cThread5.start();
cThread6.start();
cThread7.start();
cThread8.start();
}
}

通过管道进行线程间通信:字节流(见书)
通过管道进行线程间通信:字符流(见书)
实战:等待/通知之交叉备份


package Third;
public class DBTools {
volatile private boolean prevIsA = false;
synchronized public void backupA() {
try {
while (prevIsA == true) {
wait();
}
for (int i = 0; i < 5; i++) {
System.out.println("★★★★★");
}
prevIsA = true;
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void backupB() {
try {
while (prevIsA == false) {
wait();
}
for (int i = 0; i < 5; i++) {
System.out.println("☆☆☆☆☆");
}
prevIsA = false;
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Third;
public class BackupA extends Thread {
private DBTools dbtools;
public BackupA(DBTools dbtools) {
super();
this.dbtools = dbtools;
}
@Override
public void run() {
dbtools.backupA();
}
}
package Third;
public class BackupB extends Thread {
private DBTools dbtools;
public BackupB(DBTools dbtools) {
super();
this.dbtools = dbtools;
}
@Override
public void run() {
dbtools.backupB();
}
}
package Third;
public class Run {
public static void main(String[] args) {
DBTools dbtools = new DBTools();
for (int i = 0; i < 20; i++) {
BackupB output = new BackupB(dbtools);
output.start();
BackupA input = new BackupA(dbtools);
input.start();
}
}
}


《Java多线程编程核心技术》读后感(十)的更多相关文章
- Java多线程编程核心技术---学习分享
继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...
- Java多线程编程核心技术---对象及变量的并发访问(二)
数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...
- Java多线程编程核心技术
Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...
- 《Java多线程编程核心技术》推荐
写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...
- 《java多线程编程核心技术》(一)使用多线程
了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...
- 《Java 多线程编程核心技术》- 笔记
作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大 ...
- Thread.currentThread()和this的区别——《Java多线程编程核心技术》
前言:在阅读<Java多线程编程核心技术>过程中,对书中程序代码Thread.currentThread()与this的区别有点混淆,这里记录下来,加深印象与理解. 具体代码如下: pub ...
- Java多线程编程核心技术(三)多线程通信
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...
- Java多线程编程核心技术(二)对象及变量的并发访问
本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...
- Java多线程编程核心技术(一)Java多线程技能
1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...
随机推荐
- maven scope runtime
https://blog.csdn.net/ningbohezhijunbl/article/details/25818069 There are 6 scopes available: compil ...
- 【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA
[BZOJ4999]This Problem Is Too Simple! Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2 ...
- EasyNVR无插件播放HLS/RTMP网页直播方案前端完善:监听表单变动
在上一篇博客中我们表述完了防止提交成功后多余操作提交的一个过程:其中的精髓在于ajax的触发事件的使用. 而这篇博客主要想说明一下如何实时的判断出表单是否发生变化. 问题表述: 在网页前端的开发过程中 ...
- mysql系列之8.mysql高可用 (mha4mysql)
环境: 三台机器 主服务器: 192.168.1.130 主备机器: 192.168.1.131 监控机器: 192.168.1.132 130和131, 是mysql双主架构 1.在三台机器上安装m ...
- d3 - bar chart
用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为可缩放矢量图形(Scalable Vecto ...
- python manage.py shell 的增删改查
python manage.py shell 的增删改查 guoguo-MacBook-Pro:myblog guoguo$ python manage.py shell Python 3.5.1 ( ...
- Linux下Mysql数据库忘记root
系统环境:Red Hat Enterprise Linux Server 6 1.停止mysqld服务 [root@Server huage]# service mysqld stop 2.以跳过授权 ...
- linux删除目录下所有文件,但是保留文件夹
删除目录和子目录下所有rpm文件,但是保留文件夹,先cd到想要删除的目录 命令如下 find ./ -name "*.rpm" | xargs rm
- Gemini.Workflow 双子工作流入门教程一:定义流程:流程图属性
简介: Gemini.Workflow 双子工作流,是一套功能强大,使用简单的工作流,简称双子流,目前配套集成在Aries框架中. 下面介绍本篇教程:流程定义:流程图属性. 步骤一:在流程管理的流程定 ...
- POJ2443 Set Operation —— bitset
题目链接:https://vjudge.net/problem/POJ-2443 Set Operation Time Limit: 3000MS Memory Limit: 65536K Tot ...