迅雷笔试的一道多线程题目解答

heartraid86 2010-03-03 08:14:14

/****************************************************************
* 迅雷笔试题:
* 有三个线程ID分别是A、B、C,请有多线编程实现,在屏幕上循环打印10次ABCABC…
*
* @author: heartraid
*****************************************************************/

/**
* 锁码:公共数据区
* 码值:码值为A,表示应该由A线程来执行,B,C线程等待
* 码值为B,C同理。
*/
class LockCode{
/**当前锁码码值,初始码值为A,表示最初由A线程运行*/
private char code='A';
/**单例模式*/
private LockCode(){
}

public static LockCode newInstance(){
return new LockCode();
}
/**
* 循环设置锁码
* 每一次调用,锁码按照A-B-C-A-...-的顺序循环往复
*/
public void setCode(){
this.code=(char)(this.code+1);
if(this.code=='D')
this.code='A';
}
/**
* 得到锁码
*/
public char getCode(){
return this.code;
}
}
/**
* 完成打印工作的线程类
*/
class PrintRunnable implements Runnable{
/**需要打印的字符*/
private char character='?';
/**公共锁码*/
private LockCode lockCode=null;

PrintRunnable(char c,LockCode l){
this.character=c;
this.lockCode=l;
}
/**
* 线程执行
*/
public void run() {
int loopCount=1;
while(loopCount<=10){
synchronized(lockCode){//线程同步操作锁码
try{
//如果当前运行的线程并不等于当前锁码的码值,则改线程等待
//比如当前运行线程是A,但是码值为B,则A线程等待。
while(lockCode.getCode()!=this.character)
lockCode.wait();
//码值匹配成功,打印字符
System.out.print(this.character);
//循环10次记数
loopCount++;
//设置码值,让下一个线程可以运行
lockCode.setCode();
//让其他所有等待线程激活
lockCode.notifyAll();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}

}
/**
* 测试
*/
public class ThreadLoopPrint {

public static void main(String[] args) {
LockCode lockCode=LockCode.newInstance();//公共锁码
Thread ta=new Thread(new PrintRunnable('A',lockCode));
Thread tb=new Thread(new PrintRunnable('B',lockCode));
Thread tc=new Thread(new PrintRunnable('C',lockCode));
ta.start();
tb.start();
tc.start();
}
}
...全文
422 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
todd_liu 2011-12-29
  • 打赏
  • 举报
回复

public class QueueChannel {
private int buffer;
private final int count;
private int num;
public QueueChannel(int count){
buffer=count;
this.count = count;
num=0;
}
public synchronized void putAndPrint (char name) throws InterruptedException{
while(this.buffer!=(name-'A'>0?name-'A':this.count+name-'A')){
wait();
}
this.buffer=name-'A'+1;
System.out.println(Thread.currentThread().getName());
notifyAll();
if(num++>=10)Thread.currentThread().stop();
}
}


badhorse 2010-08-03
  • 打赏
  • 举报
回复
第一次发帖,格式没有调好,再发一次试试~~
/**
* 若干个LinkedThread线程可以依次串联起来,形成一条链(或一个环),
* 这条链(或环)的特点是:只有当上游线程执行完任务之后,下游线程才开始执行。这类似于接力赛跑的情形
* ,每个LinkedThread线程相当于一个运动员,某个运动员跑完当前赛段后,就把接力棒交给下一个运动员。
*
* @author YubingMa mmyybb3000@yahoo.com.cn QQ65302481
*
*/
public class LinkedThread extends Thread {
private LinkedThread previousThread;

public void setPreviousThread(LinkedThread previousThread) {
this.previousThread = previousThread;
}

public LinkedThread(LinkedThread previousThread, String msgToPrint) {
this.previousThread = previousThread;
this.msgToPrint = msgToPrint;
}

// 指示本线程是否已经完成当前任务。可以将此变量想象成一个接力棒。
private boolean isFinished;

private String msgToPrint;

private static final int roundCount = 10; // 重复执行任务的次数,可想象为接力赛跑的圈数

public void run() {
try {
for (int i = 0; i < roundCount; i++) {
waitPreviousThreadToFinish();
doSomething();
setFinishedFlag();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private void waitPreviousThreadToFinish() throws InterruptedException {
synchronized (previousThread) {
while (!previousThread.isFinished) {
previousThread.wait();
}
}

previousThread.isFinished = false;
}

/**
* 设置本线程为“任务已完成”状态,这将触发下游线程的执行。
*/
private void setFinishedFlag() {
synchronized (this) {
isFinished = true;
this.notifyAll();
}
}

private void doSomething() throws InterruptedException {
System.out.print(msgToPrint);
}

public static void main(String[] args) throws InterruptedException {
// 创建若干个线程,这些线程被串联成一个有向环,只有当上游线程执行完成之后,下游线程才会执行
LinkedThread threadA = new LinkedThread(null, "A");
LinkedThread threadB = new LinkedThread(threadA, "B");
LinkedThread threadC = new LinkedThread(threadB, "C ");
threadA.setPreviousThread(threadC); // 线程C成为A的上游,这样就形成一个封闭的环

threadA.start();
threadB.start();
threadC.start();
threadC.setFinishedFlag(); // 设置线程C为“已完成”状态,这将触发下游线程(线程A)开始执行
}
}
badhorse 2010-08-03
  • 打赏
  • 举报
回复
/**
* 若干个LinkedThread线程可以依次串联起来,形成一条链(或一个环),
* 这条链(或环)的特点是:只有当上游线程执行完任务之后,下游线程才开始执行。这类似于接力赛跑的情形
* ,每个LinkedThread线程相当于一个运动员,某个运动员跑完当前赛段后,就把接力棒交给下一个运动员。
*
* @author Yubing Ma
*
*/
public class LinkedThread extends Thread {
private LinkedThread previousThread;

public void setPreviousThread(LinkedThread previousThread) {
this.previousThread = previousThread;
}

public LinkedThread(LinkedThread previousThread, String msgToPrint) {
this.previousThread = previousThread;
this.msgToPrint = msgToPrint;
}

// 指示本线程是否已经完成当前任务。可以将此变量想象成一个接力棒。
private boolean isFinished;

private String msgToPrint;

private static final int roundCount = 10; // 重复执行任务的次数,可想象为接力赛跑的圈数

public void run() {
try {
for (int i = 0; i < roundCount; i++) {
waitPreviousThreadToFinish();
doSomething();
setFinishedFlag();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private void waitPreviousThreadToFinish() throws InterruptedException {
synchronized (previousThread) {
while (!previousThread.isFinished) {
previousThread.wait();
}
}

previousThread.isFinished = false;
}

/**
* 设置本线程为“任务已完成”状态,这将触发下游线程的执行。
*/
private void setFinishedFlag() {
synchronized (this) {
isFinished = true;
this.notifyAll();
}
}

private void doSomething() throws InterruptedException {
System.out.print(msgToPrint);
}

public static void main(String[] args) throws InterruptedException {
// 创建若干个线程,这些线程被串联成一个有向环,只有当上游线程执行完成之后,下游线程才会执行
LinkedThread threadA = new LinkedThread(null, "A");
LinkedThread threadB = new LinkedThread(threadA, "B");
LinkedThread threadC = new LinkedThread(threadB, "C ");
threadA.setPreviousThread(threadC); // 线程C成为A的上游,这样就形成一个封闭的环

threadA.start();
threadB.start();
threadC.start();
threadC.setFinishedFlag(); // 设置线程C为“已完成”状态,这将触发下游线程(线程A)开始执行
}
}
hjh811 2010-03-04
  • 打赏
  • 举报
回复
顶 明天来看~~~~
duanjianbo26 2010-03-04
  • 打赏
  • 举报
回复

import java.util.HashMap;
import java.util.Map;

public class Xunlei {

private Object lock=new Object();
private static Map<String,Boolean> map=new HashMap<String,Boolean>();
static
{
map.put("A",true);
map.put("B",false);
map.put("C",false);

}

public static void main(String[] args)
{
Xunlei xl=new Xunlei();
xl.new taskThread("A").start();
xl.new taskThread("B").start();
xl.new taskThread("C").start();
}
public class taskThread extends Thread
{
public taskThread(String name)
{
super.setName(name);
}

public void run()
{
while(true)
{
synchronized(lock)
{
if(this.getName().equals("A"))
{

if(map.get("A"))
{
setOpen("B");
System.out.println("A");
}

}else if(this.getName().equals("B"))
{
if(map.get("B"))
{
setOpen("C");
System.out.println("B");
}
}else if(this.getName().equals("C"))
{
if(map.get("C"))
{
setOpen("A");
System.out.println("C");
}
}


}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {

e.printStackTrace();
}
}
}
}

public void setOpen(String key)
{
for(Map.Entry<String, Boolean> m:map.entrySet())
{
map.put(m.getKey(), false);
}
map.put(key, true);
}
}

冰思雨 2010-03-03
  • 打赏
  • 举报
回复
原本是想几个线程按照创建线程实例的顺序来顺次打印的。
并且本线程打印完成会立即唤醒下一个线程,而不是唤醒所有线程,每个线程判断后阻塞不符合要求的。
实际上已经实现了当初的设计思想。
但是,由于是要唤醒下一个线程,所以,下一个线程必须在唤醒前处于阻塞状态。
这就导致,几个线程的启动顺序要倒序启动。
也算是这个程序的一个缺陷吧。
冰思雨 2010-03-03
  • 打赏
  • 举报
回复
我也大致写了一个
static class PrintThread extends Thread{
private static class Entry{
String id;
Entry next;
Entry previous;
Entry(String id){
this.id = id;
}
}
private static Entry header;
private static int MaxPrintCount = 10;
private Entry myLock;
public PrintThread(String id){
myLock=new Entry(id);
addEntry(myLock);
}
private void addEntry(Entry e) {
if(header==null){
header=e;
header.next=header.previous=e;
}else{
header.previous.next=e;
e.previous=header.previous;
header.previous=e;
e.next=header;
}
}
public void run(){
try{
for(int i=0;i<MaxPrintCount;i++){
if(!(i==0 && myLock==header)){//第一个线程首次打印不阻塞。
synchronized (myLock) {
myLock.wait();
}
}
printId();
synchronized (myLock.next) {
myLock.next.notify();
}
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
private void printId() {
System.out.print(myLock.id);
}
}
public static void main(String[] args) {
PrintThread pta = new PrintThread("A");
PrintThread ptb = new PrintThread("B");
PrintThread ptc = new PrintThread("C");
PrintThread ptd = new PrintThread("D");
//线程启动要倒序。
ptd.start();
ptc.start();
ptb.start();
pta.start();
}
  • 打赏
  • 举报
回复
也凑下热闹,思路都差不多
package self.saturday.part13;

public class Tencent {
public static void main(String[] args){
Signal s=new Signal(3);

StringPrinter
p1=new StringPrinter("A",s),
p2=new StringPrinter("B",s),
p3=new StringPrinter("C",s);

p1.start();
p2.start();
p3.start();

}
}

class StringPrinter extends Thread{
static int threadCount=0;

private Signal signal;
private String printStr;
private int order;

public StringPrinter(String str,Signal s){
signal=s;
printStr=str;
order=threadCount++;
}

public void run(){
int loopCount=0;

while(loopCount<10){
synchronized(signal){
//等待信号量
while(signal.getValue()!=order){
try {
signal.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

//执行操作
System.out.print(printStr);
signal.next();
loopCount++;

//唤醒其他线程
signal.notifyAll();
}
}
}
}

class Signal{
private int value=0;
private int signalCount;

public Signal(int count){
signalCount=count;
}

public int getValue(){
return value;
}

public void next(){
value++;
if(value==signalCount){
value=0;
}
}
}
java1109 2010-03-03
  • 打赏
  • 举报
回复
顶一个
明天再来看看
heartraid86 2010-03-03
  • 打赏
  • 举报
回复
晕,快掉下去了,继续顶
heartraid86 2010-03-03
  • 打赏
  • 举报
回复
自己先顶住,大家有好想法拿出来分享一下。

62,624

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧