匿名类的一个好处是可以很方便的访问外部的局部变量。
前提是外部的局部变量需要被声明为final。(JDK7以后就不需要了)

======================

同步方法1:普通式

同步方法2:在对象方法里 写关键字,用this

同步方法3:在方法前,加上修饰符synchronized,效果等同方法2

==================

题目1--同步查找文件内容

把 练习-查找文件内容 改为多线程查找文件内容
原练习的思路是遍历所有文件,当遍历到文件是 .java的时候,查找这个文件的内容,查找完毕之后,再遍历下一个文件

现在通过多线程调整这个思路:
遍历所有文件,当遍历到文件是.java的时候,创建一个线程去查找这个文件的内容,不必等待这个线程结束,继续遍历下一个文件

package zsc.czy.zhonghe;import java.io.File;
import java.io.FileReader;public class findContent {public static void main(String[] args) {File f = new File("d:/test");search(f, "Hello");}public static void search(File f, String search) {System.out.println(f); //d:\find.txtSystem.out.println(f.getAbsolutePath());
//      System.out.println(f.getName());//find.txtif (f.isFile()) {if (f.getName().toLowerCase().endsWith(".java")) {new Thread(new Runnable() {@Overridepublic void run() {String fileContent = readFileConent(f);if (fileContent.contains(search)) {System.out.printf("找到子目标字符串%s,在文件:%s%n", search, f);}}}).start();}}if(f.isDirectory()){File[] fs = f.listFiles();for(File file :fs){search(file,search);}}}private static String readFileConent(File f) {try (FileReader fr = new FileReader(f);) {char[] c = new char[(int) f.length()];fr.read(c);String s = new String(c);return s;} catch (Exception e) {return null;}}
}

题目2--英雄充能

英雄有可以放一个技能叫做: 波动拳-a du gen。
每隔一秒钟,可以发一次,但是只能连续发3次。

发完3次之后,需要充能5秒钟,充满,再继续发。

package zsc.czy.thread;public class Hero {String name;int hp;int damage;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getHp() {return hp;}public void setHp(int hp) {this.hp = hp;}public int getDamage() {return damage;}public void setDamage(int damage) {this.damage = damage;}public boolean isDead() {return 0 >= hp ? true : false;}public void attackHero(Hero h) {try {// 为了表示攻击需要时间,每次攻击暂停1000毫秒Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}h.hp -= damage;System.out.format("%s 正在攻击 %s,%s的血编程了 %.0f%n", name, h.name, h.name,h.hp);if (h.isDead()) {System.out.println(h.name + "死了");}}int totalTime = 3;public void adugen() {while (true) {for (int i = 0; i < totalTime; i++) {System.out.printf("波动拳第%d发%n", i + 1);try {Thread.sleep(1000);} catch (Exception e) {// TODO: handle exception}}System.out.println("开始为时5秒的充能");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {Hero h = new Hero();h.name = "红仔";h.adugen();}
}

题目3--破解密码

  1. 生成一个长度是3的随机字符串,把这个字符串作为当做密码

  2. 创建一个破解线程,使用穷举法,匹配这个密码

  3. 创建一个日志线程,打印都用过哪些字符串去匹配,这个日志线程设计为守护线程

提示: 破解线程把穷举法生成的可能密码放在一个容器中,日志线程不断的从这个容器中拿出可能密码,并打印出来。 如果发现容器是空的,就休息1秒,如果发现不是空的,就不停的取出,并打印。

==============================

HashMap不严格 可以存放 null --不是线程安全的类
Hashtable严格

ArrayList是非线程安全的
Vector是线程安全的类

====================

题目4-线程安全的MyStack

借助把非线程安全的集合转换为线程安全,用另一个方式完成 练习-线程安全的MyStack

题目5--死锁

3个同步对象a, b, c
3个线程 t1,t2,t3

故意设计场景,使这3个线程彼此死锁

//我这样设计是不成功的
package zsc.czy.thread;public class SiSuo {public static void main(String[] args) {final Hero ahri = new Hero();ahri.name = "九尾妖狐";final Hero annie = new Hero();annie.name = "安妮";final Hero leqing = new Hero();annie.name = "李青";Thread t1 = new Thread() {public void run() {// 占有九尾妖狐synchronized (ahri) {System.out.println("t1 已占有九尾妖狐");try {// 停顿1000毫秒,另一个线程有足够的时间占有安妮Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("t1 试图占有安妮");System.out.println("t1 等待中 。。。。");synchronized (annie) {System.out.println("do something");}}}};t1.start();Thread t2 = new Thread() {public void run() {// 占有安妮synchronized (annie) {System.out.println("t2 已占有安妮");try {// 停顿1000秒,另一个线程有足够的时间占有暂用九尾妖狐Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("t2 试图占有李青");System.out.println("t2 等待中 。。。。");synchronized (leqing) {System.out.println("do something");}}}};t2.start();Thread t3 = new Thread(){public void run() {synchronized (leqing) {System.out.println("t3已占有李青");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t3 试图占有九尾妖狐");System.out.println("t3 等待中 。。。。");}synchronized (ahri) {System.out.println("do something");}};};t3.start();}
}

正确做法为:

package multiplethread;public class TestThread {public static void main(String[] args) {Object a = new Object();Object b = new Object();Object c = new Object();Thread t1 =new Thread(){public void run(){synchronized (a) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (b) {synchronized (c) {}}}  }};Thread t2 =new Thread(){public void run(){synchronized (c) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (a) {synchronized (b) {}}}  }};Thread t3 =new Thread(){public void run(){synchronized (b) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (c) {synchronized (a) {}}}  }};t1.start();t2.start();t3.start();}}

================

使用wait和notify进行线程交互

this.wait()表示 让占有this的线程等待,并临时释放占有
this.notify() 表示通知那些等待在this的线程,可以苏醒过来了。

public synchronized void recover() {hp = hp + 1;System.out.printf("%s 回血1点,增加血后,%s的血量是%.0f%n", name, name, hp);// 通知那些等待在this对象上的线程,可以醒过来了,如第20行,等待着的减血线程,苏醒过来this.notify();}// 掉血  同步方式和上面效果一样 这个方式public void hurt() {synchronized (this) {if (hp == 1) {// 让占有this的减血线程,暂时释放对this的占有,并等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}hp = hp - 1;System.out.printf("%s 减血1点,减少血后,%s的血量是%.0f%n", name, name, hp);}}

别忘了Thread 父类也是Object

题目--线程交互

假设加血线程运行得更加频繁,英雄的最大血量是1000

设计加血线程和减血线程的交互,让回血回满之后,加血线程等待,直到有减血线程减血

    // 回血public synchronized void recover() {if(hp>=1000){try {this.wait(); //后加的} catch (InterruptedException e) {e.printStackTrace();}}hp = hp + 1;System.out.printf("%s 回血1点,增加血后,%s的血量是%.0f%n", name, name, hp);// 通知那些等待在this对象上的线程,可以醒过来了,如第73行,等待着的减血线程,苏醒过来this.notify(); }// 掉血  同步方式和上面效果一样 这个方式public void hurt() {synchronized (this) {if (hp == 1) {// 让占有this的减血线程,暂时释放对this的占有,并等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}hp = hp - 1;System.out.printf("%s 减血1点,减少血后,%s的血量是%.0f%n", name, name, hp);//notify() 的意思是,通知一个等待在这个同步对象上的线程,你可以苏醒过来了,有机会重新占用当前对象了。//掉血之后,唤醒等待的线程this.notify();//后加的}}

题目--多线程交互

在上面的练习的基础上,增加回血线程到2条,减血线程到5条,同时运行。

运行一段时间,观察会发生的错误,分析错误原因,并考虑解决办法

题目--生产者消费者问题

生产者消费者问题是一个非常典型性的线程交互的问题。

  1. 使用栈来存放数据
    1.1 把栈改造为支持线程安全
    1.2 把栈的边界操作进行处理,当栈里的数据是0的时候,访问pull的线程就会等待。 当栈里的数据时200的时候,访问push的线程就会等待
  2. 提供一个生产者(Producer)线程类,生产随机大写字符压入到堆栈
  3. 提供一个消费者(Consumer)线程类,从堆栈中弹出字符并打印到控制台
  4. 提供一个测试类,使两个生产者和三个消费者线程同时运行,结果类似如下 :

==================

Lock

题目

在练习-线程安全的MyStack 练习中,使用synchronized把MyStack修改为了线程安全的类。

接下来,借助Lock把MyStack修改为线程安全的类

把synchronized去掉
使用lock占用锁
使用unlock释放锁
必须放在finally执行,万一heros.addLast抛出异常也会执行

package multiplethread;import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;import charactor.Hero;public class MyStack {LinkedList<Hero> heros = new LinkedList<Hero>();Lock lock = new ReentrantLock();//把synchronized去掉public  void push(Hero h) {try{//使用lock占用锁lock.lock();heros.addLast(h);          }finally{//使用unlock释放锁//必须放在finally执行,万一heros.addLast抛出异常也会执行lock.unlock();}}//把synchronized去掉public  Hero pull() {try{//使用lock占用锁lock.lock();return heros.removeLast();         }finally{//使用unlock释放锁//必须放在finally执行,万一heros.removeLast();抛出异常也会执行          lock.unlock();}}public Hero peek() {return heros.getLast();}public static void main(String[] args) {}}

题目--借助tryLock 解决死锁问题

当多个线程按照不同顺序占用多个同步对象的时候,就有可能产生死锁现象。

死锁之所以会发生,就是因为synchronized 如果占用不到同步对象,就会苦苦的一直等待下去,借助tryLock的有限等待时间,解决死锁问题

package multiplethread;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TestThread {public static void main(String[] args) throws InterruptedException {Lock lock_ahri = new ReentrantLock();Lock lock_annie = new ReentrantLock();Thread t1 = new Thread() {public void run() {// 占有九尾妖狐boolean ahriLocked = false;boolean annieLocked = false;try {ahriLocked = lock_ahri.tryLock(10, TimeUnit.SECONDS);if (ahriLocked) {System.out.println("t1 已占有九尾妖狐");// 停顿1000秒,另一个线程有足够的时间占有安妮Thread.sleep(1000);System.out.println("t1 试图在10秒内占有安妮");try {annieLocked = lock_annie.tryLock(10, TimeUnit.SECONDS);if (annieLocked)System.out.println("t1 成功占有安妮,开始啪啪啪");else{System.out.println("t1 老是占用不了安妮,放弃");}} finally {if (annieLocked){System.out.println("t1 释放安妮");lock_annie.unlock();}}}} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} finally {if (ahriLocked){System.out.println("t1 释放九尾狐");lock_ahri.unlock();}}}};t1.start();Thread.sleep(100);Thread t2 = new Thread() {public void run() {boolean annieLocked = false;boolean ahriLocked = false;try {annieLocked = lock_annie.tryLock(10, TimeUnit.SECONDS);if (annieLocked){System.out.println("t2 已占有安妮");// 停顿1000秒,另一个线程有足够的时间占有安妮Thread.sleep(1000);System.out.println("t2 试图在10秒内占有九尾妖狐");try {ahriLocked = lock_ahri.tryLock(10, TimeUnit.SECONDS);if (ahriLocked)System.out.println("t2 成功占有九尾妖狐,开始啪啪啪");else{System.out.println("t2 老是占用不了九尾妖狐,放弃");}}finally {if (ahriLocked){System.out.println("t2 释放九尾狐");lock_ahri.unlock();}}}} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} finally {if (annieLocked){System.out.println("t2 释放安妮");lock_annie.unlock();}}}};t2.start();}
}

题目--生产者消费者问题

在练习-生产者消费者问题这个练习中,是用wait(), notify(), notifyAll实现了。

接下来使用Condition对象的:await, signal,signalAll 方法实现同样的效果

package multiplethread;import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class MyStack<T> {LinkedList<T> values = new LinkedList<T>();Lock lock = new ReentrantLock();Condition condition = lock.newCondition();public void push(T t) {try {lock.lock();while (values.size() >= 200) {try {condition.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}condition.signalAll();values.addLast(t);} finally {lock.unlock();}}public T pull() {T t=null;try {lock.lock();while (values.isEmpty()) {try {condition.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}condition.signalAll();t= values.removeLast();} finally {lock.unlock();}return t;}public T peek() {return values.getLast();}
}

题目--使用AtomicInteger来替换Hero类中的synchronized

在给Hero的方法加上修饰符synchronized 这个知识点中,通过给hurt和 recover方法加上synchronized来达到线程安全的效果。

这一次换成使用AtomicInteger来解决这个问题

提示:int基本类型对应的是AtomicInteger,但是float基本类型没有对应的AtomicFloat。 所以在这个练习中,把hp改为AtomicInteger即可。

转载于:https://www.cnblogs.com/czy16/p/8996587.html

java--线程--习题集锦相关推荐

  1. [转载] Java笔试题集锦

    参考链接: 关于Java中文件名和类名的误解 Java笔试题集锦 1.MVC的各个部分都有那些技术来实现?如何实现? 答:MVC是Model-View-Controller的简写."Mode ...

  2. 2016最新Java笔试题集锦

    更新时间:2015-08-13         来源:网络投诉删除 [看准网(Kanzhun.com)]笔试题目频道小编搜集的范文"2016最新Java笔试题集锦",供大家阅读参考 ...

  3. Java面试题集锦(含答案)

    Java面试题集锦 Java基础 1.ArrayList.Vector和LinkedList有什么区别? 答:ArrayList底层实现是数组,查找快,增删慢,线程不安全 Vector 和ArrayL ...

  4. 四种Java线程池用法解析

    四种Java线程池用法解析 本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 ...

  5. 【java线程】锁机制:synchronized、Lock、Condition

    [Java线程]锁机制:synchronized.Lock.Condition 原创 2013年08月14日 17:15:55 标签:Java /多线程 74967 http://www.infoq. ...

  6. java线程安全总结 - 1 (转载)

    原文地址:http://www.jameswxx.com/java/java%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E6%80%BB%E7%BB%93/ 最近想将ja ...

  7. java线程钥匙_Java多线程并发编程/锁的理解

    一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...

  8. 面试必问---Java线程池8大拒绝策略

    前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发.而不论你用Fix ...

  9. Java线程怎样映射到操作系统线程

    先说多线程模型,参考经典教材<Operating System Concepts , Silberschatz ,9th edition> 中文版是<操作系统概念,第9版> h ...

  10. java线程的优先级是数字越大优先级越高_《深入理解Java虚拟机》5分钟速成:12章(Java内存模型与线程)...

    第12章 Java内存模型与线程 前言: 1.物理机如何处理并发问题? 2.什么是Java内存模型? 3.原子性.可见性.有序性的具体含义和应用实现? 4.volatile 关键字特性? 5.基于vo ...

最新文章

  1. MS UC 2013-0-虚拟机-标准化-部署-3-虚拟机-生产
  2. [20160513]Restrict Session与静态监听.txt
  3. Spring Boot 常见面试题
  4. 堆栈和堆得区别与垃圾回收
  5. 库克:iPhone 12更新换代用户数达到顶峰
  6. redhat6与7版本进入单用户模式修改root账户密码
  7. PaddlePaddle飞桨OCR文本检测——检测模型训练(二)
  8. python2中可以使用print()函数吗_Python3中的 print 函数有哪些用法?
  9. 【Java方法】统计数组内不同元素个数及每个元素的数量
  10. 【网络工程师】 H3C如何配置VLAN-trunk 二层隔离技术
  11. ASCII,UTF-8,GBK编码简介
  12. html什么是一级标题,一级标题是什么(论文一二三级标题范本)
  13. 革命三部曲系列——《邪不压正》中,究竟布了多大的一个局!
  14. 2021/04/10 OJ每日一题 1190: 按出生日期排序(结构体专题)python
  15. php strict_types
  16. xmlHttp.send(null)与xmlHttp.send…
  17. 算法设计与分析——Johnson Trotter算法
  18. 如何管理计算机中文件,如何管理电脑文件
  19. 宝尚炒股杠杆近期部分上下环绕动摇的节奏
  20. ceph报 daemons have recently crashed

热门文章

  1. (转)非常完善的Log4net详细说明
  2. svn提交代码失败提示清理(清理失败并且报错信息乱码解决办法)
  3. mbed OS - ARM关于物联网(IoT)的战略布局
  4. Spring+Struts集成(方案一)
  5. Node.js 功能函数
  6. C++---显示实例化与隐式实例化,显示调用与隐式调用
  7. 女人离婚后不要孩子,你怎么看?
  8. 好想找一个灵魂伴侣,然后带着他一起周游世界,会实现吗?
  9. 人寿保险分红型的十年能取出来吗?
  10. 教培机构实际运营过程中会遇到的问题