通过几天的认真阅读,发现这是一本难得一见的好书,为了加深巩固学习成功,我打算将书中的例子全部自己实现一遍,特此记录下来也方便其他朋友学习。

第一章,java语言的线程

单线程程序:打印10000次good字符串

public class SingleThreadSample {
public static void main(String[] args) {
for(int i=0; i< 10000; i++){
System.out.print("good!");
}
}
}

严格的说并不是只有一个线程在操作,还有其他的线程在非java处理系统上运行,比如gc,gui相关的线程等。

第一个多线程程序:实现了交替打印good和nice的功能

public class MyThreadTest {

	public static void main(String[] args) {
MyThread t = new MyThread();
t.start(); for (int i = 0; i < 10000; i++) {
System.out.println("good!");
}
}
} class MyThread extends Thread { @Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println("nice!");
}
}
}

这里加入一个并发和并行概念的区别,并发是concurrent,是指多个线程在同一个cpu上切换进行执行。并行是parallel,指多个线程是在各自的cpu上同时执行的。

我们增强一下刚才的多线程例子,把打印的字符串变成通过参数传递。

public class MyThread2Test {
public static void main(String[] args) {
MyThread2 t1 = new MyThread2("good!");
MyThread2 t2 = new MyThread2("nice!"); t1.start();
t2.start();
} } class MyThread2 extends Thread {
private String message; public MyThread2(String message) {
this.message = message;
} @Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(message);
}
}
}

  

刚才是通过集成Thread抽象类的子类方式实现多线程,另外还可以通过Runnable接口的方式,例子如下:

public class MyThread3Test {
public static void main(String[] args) {
MyThread3 t1 = new MyThread3("good!");
MyThread3 t2 = new MyThread3("nice!"); new Thread(t1).start();
new Thread(t2).start();
}
} class MyThread3 implements Runnable {
private String message; public MyThread3(String message) {
this.message = message;
} @Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(message);
}
}
}

  

启动和执行多线程已经说完了,那么该说说如何让线程休息休息。

第一种方式是通过Thread.sleep(ms)方法,需要注意的是这个方法有一个重载Thread.sleep(ms,ns),可以把停止的时间控制到纳秒级。

另外Thread.yield()方法也可以在循环体中使用,表示如果没有cpu时间则将当前线程切换到其他子线程,可以简单理解成Thread.sleep(0);

不过Thread.sleep会抛出InterruptedException异常,Thread.yield不会。

下面在说说线程互斥,还是刚才的例子,如果我打算让程序执行10000次打印的过程是一个整体,执行过程中不允许切换到其他子线程,那么就需要使用Synchronzed关键字。

public class MyThreadMutualTest {
public static void main(String[] args) {
PrintMessage pmsg = new PrintMessage(); new MyThreadMutual(pmsg,"good").start();
new MyThreadMutual(pmsg,"nice").start();
}
} class MyThreadMutual extends Thread {
private String message;
private PrintMessage printMessage; public MyThreadMutual(PrintMessage printMessage,String message) {
this.printMessage = printMessage;
this.message=message;
} @Override
public void run() {
printMessage.show(message);
}
} class PrintMessage { public synchronized void show(String msg) {
for (int i = 0; i < 10000; i++) {
System.out.println(msg);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

  

 

接下来讲一下线程的协调,主要有三个方法:wait() notify() notifyAll()

这三个方法都是object类的方法,可以理解成一个休息室,调用obj.wait()方法表示当前执行的线程进入休息室,休息室里可能会有多个线程,如果没有其他线程给休息室发消息通知它们可以出去了,这些线程就会一直在里面休息。

当调用obj.notify()方法,表示休息室中可以有一个线程退出,如果里面有多个线程,会随机选取一个,而obj.notifyAll()表示所有的线程都可以退出休息室。

现在把上面的例子修改一下,想打印10次good再打印10次nice,这样交替执行。

public class ThreadMutualTest2 {
public static void main(String[] args) {
Object obj = new Object();
MyThreadMutualA a = new MyThreadMutualA("nice", obj);
MyThreadMutualB b = new MyThreadMutualB("good", obj); a.start();
b.start();
}
} class MyThreadMutualA extends Thread {
private Object obj;
private String message; public MyThreadMutualA(String message, Object obj) {
this.message=message;
this.obj=obj;
} @Override
public void run() {
synchronized(obj){
for(int i=1; i<100; i++){
System.out.println(message); if(i%5==0){
obj.notify(); try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} obj.notify();
}
}
} class MyThreadMutualB extends Thread { private Object obj;
private String message; public MyThreadMutualB(String message, Object obj) {
this.message=message;
this.obj=obj;
} @Override
public synchronized void run() {
synchronized(obj){
for(int i=1; i<100; i++){
System.out.println(message);
if(i%5==0){
obj.notify(); try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} obj.notify();
}
}
}

  

这段代码废了好大劲啊,同步互斥是多线程最复杂的最核心的部分了。

Java多线程设计模式系列的更多相关文章

  1. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  2. java多线程设计模式

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt220 java多线程设计模式 java语言已经内置了多线程支持,所有实现Ru ...

  3. [温故]图解java多线程设计模式(一)

    去年看完的<图解java多线程设计模式>,可惜当时没做笔记,导致后来忘了许多东西,打算再温习下这本书,顺便在这里记录一下~  1.顺序执行.并行.并发 顺序执行:多个操作按照顺序依次执行. ...

  4. Java多线程干货系列—(四)volatile关键字

    原文地址:http://tengj.top/2016/05/06/threadvolatile4/ <h1 id="前言"><a href="#前言&q ...

  5. Java多线程设计模式(一)

    目录(?)[-] Java多线程基础 Thread类的run方法和start方法 线程的启动 线程的暂时停在 线程的共享互斥 线程的协调 Single Threaded Execution Patte ...

  6. Java多线程设计模式(4)线程池模式

    前序: Thread-Per-Message Pattern,是一种对于每个命令或请求,都分配一个线程,由这个线程执行工作.它将“委托消息的一端”和“执行消息的一端”用两个不同的线程来实现.该线程模式 ...

  7. Java多线程干货系列—(一)Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  8. Java多线程开发系列之四:玩转多线程(线程的控制2)

    在上节的线程控制(详情点击这里)中,我们讲解了线程的等待join().守护线程.本节我们将会把剩下的线程控制内容一并讲完,主要内容有线程的睡眠.让步.优先级.挂起和恢复.停止等. 废话不多说,我们直接 ...

  9. Java多线程干货系列(1):Java多线程基础

    原文出处: 嘟嘟MD 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程 ...

随机推荐

  1. 模拟+算贡献——cf1195D

    比赛的时候没看到模数,用java大数在写,最后看到的时候已经慌了.. 把贡献算清楚就可以 下面是贡献的推导 有五位数 abcde * 10个 有两位数 fg * 3 个 那么这两种数组成的情况就是 a ...

  2. jQuery.speech实现文本转语音播报功能

    先放一个实例的地址https://github.com/wenco/speech jQuery.speech是用jQuery写的扩展插件,主要是用来语音播报. 接口调用百度翻译的接口,所以存在url参 ...

  3. APIO 2007 风铃

    题目描述 你准备给弟弟 Ike 买一件礼物,但是,Ike 挑选礼物的方式很特别:他只喜欢那些能被他排成有序形状的东西. 你准备给 Ike 买一个风铃.风铃是一种多层的装饰品,一般挂在天花板上. 每个风 ...

  4. CF1265B Beautiful Numbers

    题意 给一个长度为\(n\)的排列\(P\),求对于\(1\) 到 \(n\)中的每个数\(m\),是否能找到一段长度为\(m\)的区间使得区间内的数是一个\(1\)到\(m\)的排列. 输出一个\( ...

  5. spring boot读取自定义配置文件时乱码解决办法

    @PropertySource(value = "classpath:book.yml", ignoreResourceNotFound = true,encoding = &qu ...

  6. iOS开发静态库冲突——如何查看静态库(.O)中方法名

    1.bug产生 应用第三方静态库之后提示冲突错误: 2.bug分析 一般会提示哪两个库冲突: CameraShowGLView.o是自己创建的类编译生成的: libLechangeSDK.a是添加的静 ...

  7. 10、 导出python脚本进行数据驱动的接口测试

    postman自带脚本导出功能,对于代码小白来说,可以不错的学习代码级接口测试 第一步:输入接口地址,点击send 第二步:点击code,导出脚本文件,为python脚本 第三步:安装python3以 ...

  8. C#委托的实质

    1,委托时方法指针: 2,委托时一个类,对其进行实例化的时候,要将引用的方法作为他的构造方法的参数.

  9. jquery实现点击按钮弹出层和点击空白处隐藏层

    昨天做项目遇到一个问题,和大家分享下,jquery实现点击按钮弹出层和点击空白处隐藏层的问题 if($('.autoBtn').length){                $('.autoBtn' ...

  10. 活动:月末送Java技术书福利|抽奖

    本公众号运营了快一年了 原创干货超过200+ 收获了也快1W粉丝 这么多粉丝-- 送书活动怎能少? 虽然这次我们是有备而来 但是-- 所有书籍为作者自掏腰包 所以本次送书数量有限 不能满足到所有人 重 ...