背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题。晚上闲着没事就决定把它实现出来。

题目:

1.开启两个线程,一个线程打印A~Z,两一个线程打印1~52的数据。

2.实现交替打印,输出结果为12A34B...........5152Z.

3.请用多线程方式实现。

这种只有两个线程交替打印数据的题目其实相对还是比较简单的,如果利用传统线程无非就是synchronized(线程互斥)与wait(),notify()的问题。

今天不用传统线程解决这个问题,我们用Java 1.5提供的线程并发库中的类来实现这个功能(实现流程和传统线程一样)

下面是实现代码(我都加了注释,如果还是不同大家可以查看Java 1.5以上的帮助文档)

package cn.yw.thread.practice;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* 多线程练习:
* 1.开启一个线程打印1~52,开启另一个线程打印A~Z
* 打印方式:12A34B46C依次打印
* @author yw-tony
*
*/
public class PracticeTest { public static void main(String[] args){
final DataPrint data = new DataPrint();
//打印字母的线程(大家也可以把这两个线程抽取出来作为两个单独的类,这里为了实现简单我就直接写在main方法中了)
new Thread(new Runnable(){
@Override
public void run() {
while(data.letterFlag){
data.printLetter();
}
}
}).start(); //打印数字的线程
new Thread(new Runnable(){
@Override
public void run() {
while(data.numFlag){
data.printNun();
}
}
}).start(); }
/**
* 打印类
* @author yw-tony
*
*/
static class DataPrint{
public boolean letterFlag = true;//线程结束标记;
public boolean numFlag = true;
//数字的初始值
int num = 1;
//字母的初始值
//这里A~Z的字母对应的阿拉伯数字为65~90,
int letter = 65;
//线程等待标记
boolean flag = true;
//java线程并发库中的锁相当与(synchronized)
Lock lock = new ReentrantLock();
//线程并发库中用于线程之间通讯的类相当于wait(),notify()
Condition condLetter = lock.newCondition();
Condition condNum = lock.newCondition();
/**
* 打印字字母的方法
*
*/
public void printLetter(){
//如果打印到Z则结束线程并停止
if(letter >= 90 ){
letterFlag = false;
return ;
}
//锁定代码块,锁定时其他线程不能访问其中内容
lock.lock();
try{
if(flag){//如果执行打印数字的线程正在执行,则该线程进入等待状态
condLetter.await();
}
System.out.println(Thread.currentThread().getName()+":"+(char)letter);
letter++;
Thread.sleep(100);
//打印执行完成,唤醒打印数字的线程
flag = true;
condNum.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
//解锁当前代码快
lock.unlock();
} }
/**
* 打印数字的方法
*/
public void printNun(){
//如果打印到52则结束线程并停止
if(num>=52){
numFlag = false;
return;
}
lock.lock();
try{
if(!flag){
condNum.await();
}
System.out.println(Thread.currentThread().getName()+":"+num);
num++;
System.out.println(Thread.currentThread().getName()+":"+num);
num++;
Thread.sleep(100);
flag = false;
condLetter.signal();//唤醒打印字母的线程
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
}

使用Java线程并发库实现两个线程交替打印的线程题的更多相关文章

  1. Java多线程与并发库高级应用-java5线程并发库

    java5 中的线程并发库 主要在java.util.concurrent包中 还有 java.util.concurrent.atomic子包和java.util.concurrent.lock子包 ...

  2. 线程高级应用-心得5-java5线程并发库中Lock和Condition实现线程同步通讯

    1.Lock相关知识介绍 好比我同时种了几块地的麦子,然后就等待收割.收割时,则是哪块先熟了,先收割哪块. 下面举一个面试题的例子来引出Lock缓存读写锁的案例,一个load()和get()方法返回值 ...

  3. java--加强之 Java5的线程并发库

    转载请申明出处:http://blog.csdn.net/xmxkf/article/details/9945499 01. 传统线程技术回顾 创建线程的两种传统方式: 1.在Thread子类覆盖的r ...

  4. 03.Java多线程并发库API使用2

    1.多个线程之间共享数据的方式探讨 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. 2.如果每个线程执行的代 ...

  5. 线程高级应用-心得8-java5线程并发库中同步集合Collections工具类的应用及案例分析

    1.  HashSet与HashMap的联系与区别? 区别:前者是单列后者是双列,就是hashmap有键有值,hashset只有键: 联系:HashSet的底层就是HashMap,可以参考HashSe ...

  6. 线程高级应用-心得4-java5线程并发库介绍,及新技术案例分析

    1.  java5线程并发库新知识介绍 2.线程并发库案例分析 package com.itcast.family; import java.util.concurrent.ExecutorServi ...

  7. java高并发系列 - 第5天:深入理解进程和线程

    进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.程序是指令.数据及其组织形式的描述,进程是程序的实体. 进程具有的 ...

  8. Java多线程(六) —— 线程并发库之并发容器

    参考文献: http://www.blogjava.net/xylz/archive/2010/07/19/326527.html 一.ConcurrentMap API 从这一节开始正式进入并发容器 ...

  9. Java多线程(五) —— 线程并发库之锁机制

    参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...

随机推荐

  1. JavaSE——打印流

    打印流: 类PrintStream: PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式.它还提供其他两项功能.与其他输出流不同,PrintStream 永远不会抛 ...

  2. FI配置步骤清单.枫

    1.    说明 本版本的FI模块配置内容非常少,主要应用的是系统默认的配置参数,但能完成基本的总帐.应收.应付操作. 配置内容包含以下几部分: 1.  基本的组织结构定义及分配,以及公司代码的全局性 ...

  3. Angular调用父Scope的函数

    app.directive('toggle', function(){ return { restrict: 'A', template: '<a ng-click="f()" ...

  4. 安卓测试【一】android sdk环境变量配置

    移动应用自动化测试的配置,先于官网下载Android SDK,然后配置环境变量. 配置android sdk环境变量 1.  新建ANDROID_HOME环境变量,变量值为SDK解压的路径 2. 追加 ...

  5. 优化EF Code First第一次请求速度

    由于EF Code First模式没有模型文件,所以很多一次请求的时候速度比较慢,EF需要将对应的数据库映射关系加载到内存里面,往后请求就比较快.可以通过在程序初始化的时候增加一段代码来优化EF第一次 ...

  6. 【SPL标准库专题(8)】 Datastructures:SplFixedArray

    SplFixedArray主要是处理数组相关的主要功能,与普通php array不同的是,它是固定长度的,且以数字为键名的数组,优势就是比普通的数组处理更快. 类摘要 SplFixedArray im ...

  7. 如何监视 Azure 中的虚拟机

    通过收集.查看和分析诊断与日志数据,可以利用很多机会来监视 VM. 若要执行简单的 VM 监视,可以在 Azure 门户中使用 VM 的“概述”屏幕. 可以使用扩展在 VM 上配置诊断以收集更多指标数 ...

  8. Oracle EBS INV 释放保留

    CREATE or REPPLACE PROCEDURE RelieveReservation AS -- Common Declarations l_api_version NUMBER := 1. ...

  9. (转载)令人迷糊的Oracle递归查询(start with)

    转载地址:https://blog.csdn.net/weiwenhp/article/details/8218091 备注:如有侵权,请联系立即删除. 写代码时碰到要弄清楚Oracle的role之间 ...

  10. js-dom-动态创建html标签时,name属性的初始化问题

    当我们动态创建可包含Name属性的元素时,不能简单的使用赋值element.name = "..."来添加其Name, 而必须在创建Element时,使用document.crea ...