这几天看结城浩的《java多线程设计模式》,跟着做一些习题,有几道题目很有意思,记录下自己的体会。

首先是题目(在原书212页,书尾有解答):

public class Main {
public static void main(String[] args) {
try {
Blackhole.enter(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Blackhole {
public static void enter(Object obj) throws InterruptedException {
System.out.println("1");
magic(obj);
System.out.println("2");
synchronized (obj) {
System.out.println("3");
}
} private static void magic(Object obj){}
}

代码很简单,要求写出magic()代码,使得输出是

1
2

不能出现3.

思路:很明显要想不输出3,magic()必须得到obj锁,且不能释放才行。

    private static void magic(final Object obj) throws InterruptedException {
Thread thread = new Thread() {
@Override
public void run() {
synchronized (obj) {
synchronized (this) {
this.setName("LockNow");
this.notifyAll();
}
while (true) {
}
}
}
};
synchronized (thread) {
thread.setName("");
thread.start();
while (thread.getName().equals("")) {
thread.wait();
}
}
}

作者的思路很巧妙,通过thread.name的值来处理2个线程的执行次序。

1. 创建一个内部Thread实例thread,先不start()

2. 然后由主线程获得thread锁,并启动thread线程,然后开始等待。

3. thread线程会去获得obj锁,获得obj锁之后,该线程会修改自己name,并通知主线程。

4. 主线程发现条件满足,继续执行

刚看到答案,有个很大疑问,主线程获得thread锁之后,启动thread线程,而thread线程为了修改name,必须获得自己的锁(否则运行时会报错java.lang.IllegalMonitorStateException),这不死锁了吗?

仔细一想又不会,因为新线程开启之后,如果新线程运行到synchronized (this)被阻挡而无法修改name,主线程肯定会进入wait,而wait时主线程释放thread锁,新线程就可继续往下跑。

短短几行代码,线程之间同步协调环环相扣,不得不佩服作者的功力!

一道很有意思的java线程题的更多相关文章

  1. ZOJ2006 一道很尴尬的string操作题

    ZOJ2006(最小表示法) 题目大意:输出第一个字符串的最小字典序字串的下标! 然后我居然想试一试string的erase的能力,暴力一下,然后20msAC了,尴尬的数据.......... #in ...

  2. [BZOJ2456] mode(一道很有意思的题)

    传送门 看到这个题的第一反应是离散化+线段树乱搞.. eeeeeeeeeeee感觉数据结构学傻了,其实直接存下来,sort一遍,n/2的位置的就是答案 当然前提是空间够的话 1m的空间连数组都开不下 ...

  3. hdu 3397 Sequence operation(很有意思的线段树题)

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  4. Java线程:概念与原理

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  5. java线程详解

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  6. Java线程详解----借鉴

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  7. java 线程(1)

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  8. java线程大全一讲通

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  9. 【转】Java线程详解

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

随机推荐

  1. 【代码笔记】Web-JavaScript-JavaScript正则表达式

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  2. React 入门学习笔记整理目录

    React 入门学习笔记整理(一)--搭建环境 React 入门学习笔记整理(二)-- JSX简介与语法 React 入门学习笔记整理(三)-- 组件 React 入门学习笔记整理(四)-- 事件 R ...

  3. div 中图片溢出问题及 CSS3中图片翻转问题

    如果设置一个div 装两张以上的图片,如果不设置好div的宽度和高度,就会使图片溢出. 我们知道,div是可以由图片撑开其宽高的,也就是说如果只放一张图片的情况下,不设置div的宽高,div的宽高会默 ...

  4. Git 结合Git使用Bitbucket进行代码版本管理流程规范与实践

    结合Git使用Bitbucket进行代码版本管理流程规范与实践   By:授客 QQ:1033553122   目录 目录 1 一. 测试环境 2 二. 新建项目 2 三. 新建公有版本库 3 四. ...

  5. loadrunner 脚本优化-参数化之Parameter List参数取值

    脚本优化-参数化之Parameter List参数取值 by:授客 QQ:1033553122 参数取值选项 Select next row Update value on 以上两个选项是改变参数化取 ...

  6. Pycharm基本设置和插件安装

    Pycharm调节主题和字体 调节主题:File - Setting - Editor - Color Scheme - 选择个人喜欢的风格 调节字体大小,感觉默认字体有点小,对我这样的老人家,至少要 ...

  7. (jQuery插件)autocomplete插件的简单例子

    1.引入相应的js和css,我用到的时候是在jquery-ui的js里面整合的,ui的css 2.先在html上写一个input <input id="tags" class ...

  8. Python之__new__方法

    # -*- coding: utf-8 -*- """ Created on Sun Dec 2 11:03:03 2018 Python类构造过程 @author: z ...

  9. kali2016.2(debian)快速安装mysql5.7.17

    糊里糊涂的删除了kali原本的mysql5.6.27版本,原本的mysql与很多软件关联在一起,每次安装都失败,后来把相关的都卸载了(悲催的浪费了一天) 下载地址  debian mysql下载地址 ...

  10. sql server 的Maintenance Plans(维护计划)详解

    下面说下我遇到的场景,就是我通过数据库自身的维护计划建立了数据库收缩自动计划,却发现数据库并没有实际性收缩. 前奏自动化配置流程 数据库--管理---维护计划--双击(维护计划向导)--下一步--名称 ...