并发编程题

A_finder 2016-03-24 06:15:56
题目:有四个线程A、B、C、D,线程A的功能是打印出A,线程B的功能是打印出B,以此类推。。
现在有四个txt文件A.TXT、B.TXT、C.TXT、D.TXT,初始都为空。
每个线程都分别将输出结果写入4个文件,要求格式如下:
A.TXT:A B C D A B C D...
A.TXT: B C D A B C D A...
C.TXT: C D A B C D A B...
D.TXT: D A B C D A B C...
水平不够,求大神指导。
...全文
326 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
rickylin86 2016-03-28
  • 打赏
  • 举报
回复

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;

import java.io.IOException;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import static java.nio.file.StandardOpenOption.*;

import java.nio.channels.WritableByteChannel;
import java.nio.ByteBuffer;

public class Test{
	public static void main(String[] args){
		String[] strs = {"A","B","C","D"};//设置写入的内容.可以无限添加长度和调整顺序
		Path file = Paths.get(System.getProperty("user.dir")).resolve("A.txt");
		int length = strs.length;
		int time = 100;//这里设置每个内容写入的次数.
		Group group = new Group(file,strs);
		Thread[] threads = new Thread[length];
		for(int i = 0 ; i < length ; i ++){
			threads[i] = new Thread(new Task(group,i,time));
		}

		for(int i = 0 ; i < length ; i ++){
			threads[i].start();
		}
		
	}
}

class Group{
	public Group(Path file,String ... contents){
		assert (Files.notExists(file) || Files.isRegularFile(file));
		try{
			channel = Files.newByteChannel(file,CREATE,WRITE,APPEND);
		}catch(IOException e){
			e.printStackTrace();
			System.exit(1);
		}
		this.length = contents.length;
		conditions = new Condition[length];
		this.contents = contents;
		for(int i = 0 ; i < length ; i ++){
			conditions[i] = lock.newCondition();
		}
		lives = new boolean[length];
		lives[0] = true;
	}

	public void process(int index){

		if(firstTimeWait){//首次让第一个线程睡眠,腾出时间让第二个线程启动.
				firstTimeWait = false;
				try{
					Thread.sleep(100);
				}catch(InterruptedException e){
					e.printStackTrace();
				}
			}
		
		try{
			lock.lock();
			
			assert index >= 0  && index < length;
			if(!lives[index]){
				conditions[index].await();
			}
			lives[index] = false;
			try{
				Thread.sleep(10);//这里需要设置等待.要不有时候处理太快会出现死锁.
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			channel.write(ByteBuffer.wrap(contents[index].getBytes()));

			if(index == length - 1){
				conditions[0].signalAll();
			}else{
				conditions[index + 1].signalAll();
			}

			lock.unlock();
			
			
		}catch(InterruptedException|IOException e){
			e.printStackTrace();
			System.exit(1);
		}
	}

	public int getLength(){
		return length;
	}
	

	private final ReentrantLock lock = new ReentrantLock();
	private final Condition[] conditions;
	private boolean[] lives;
	private final String[] contents;
	private final int length;
	private WritableByteChannel channel;
	private boolean firstTimeWait = true;
}

class Task implements Runnable{
	
	public Task(Group group,int index,int time){
		this.group = group;
		this.index = index;
		assert index < group.getLength();
		this.time = time;
	}

	@Override
	public void run(){
		for(int i = 0 ; i < time ; i ++){
			group.process(index);
			if(i == time - 1){
				Thread.currentThread().interrupt();
			}
		}
	}

	private Group group;
	private int index;
	private int time;
}
Intboy 2016-03-26
  • 打赏
  • 举报
回复
public class TestThread
{
    // private static final Log LOGGER = LogFactory.getLog(TestThread.class);

    public static void main(String[] args)
    {

        Runnable runnableA = new Runnable()
        {
            public void run()
            {
                int i = 0;
                while (i < 10)
                {
                    writeA();
                    writeB();
                    writeC();
                    i++;
                }
                System.out.println();
            }
        };
        Runnable runnableB = new Runnable()
        {
            public void run()
            {
                int i = 0;
                while (i < 10)
                {
                    writeA();
                    writeB();
                    writeC();
                    i++;
                }
                System.out.println();
            }
        };
        Runnable runnableC = new Runnable()
        {
            public void run()
            {
                int i = 0;
                while (i < 10)
                {
                    writeA();
                    writeB();
                    writeC();
                    i++;
                }
                System.out.println();
            }
        };

        Thread threadA = new Thread(runnableA);
        Thread threadB = new Thread(runnableB);
        Thread threadC = new Thread(runnableC);

        threadA.start();
        threadB.start();
        threadC.start();
    }

    static String flagA = "A";
    static String flagB = "B";
    static String flagC = "C";

    private static void writeA()
    {
        ReentrantLock lock = new ReentrantLock();
        try
        {
            lock.lock();
            if (flagA.equals("A"))
            {
                System.out.print("A");
                flagA = "B";
            }
        } finally
        {
            lock.unlock();
        }
    }

    private static void writeB()
    {
        ReentrantLock lock = new ReentrantLock();
        try
        {
            lock.lock();
            if (flagB.equals("B"))
            {
                System.out.print("B");
                flagA = "C";
            }
        } finally
        {
            lock.unlock();
        }
    }

    private static void writeC()
    {
        ReentrantLock lock = new ReentrantLock();
        try
        {
            lock.lock();
            if (flagC.equals("C"))
            {
                System.out.print("C");
                flagA = "A";
            }
        } finally
        {
            lock.unlock();
        }
    }
}
Spinach007 2016-03-25
  • 打赏
  • 举报
回复
我也是刚学一个月。感觉只要重写4个线程的run方法就行了吧?run方法体里面循环写入字母。 刚学么也别想着 写出多简洁牛逼又能实现功能的代码, 不管怎么样写得怎么样,先实现了再说优化的事
A_finder 2016-03-25
  • 打赏
  • 举报
回复
楼上代码我运行一下,与题意有出入,线程A的功能是打印出A,不能打印其他字符串。不过思路可以参考。
A_finder 2016-03-25
  • 打赏
  • 举报
回复
楼上代码我运行一下,与题意有出入,线程A的功能是打印出A,不能打印其他字符串。不过思路可以参考。
  • 打赏
  • 举报
回复
其实很简单 采用thread.join()方法即可实现 代码片段可见: package com.jing.test.thread; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; /** * 打印线程类 * @author jtj * */ public class PrintRun implements Runnable { private String printStr ; private String fileName ; public PrintRun(String printStr,String filename) { this.printStr = printStr ; this.fileName = filename ; } @Override public void run() { BufferedWriter writer = null ; File file = new File(this.fileName) ; try { if(!file.isFile()){ file.createNewFile() ; } writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true))) ; writer.write(printStr); System.err.println(fileName + "存放的数据有: " +printStr); } catch (Exception e) { e.printStackTrace(); }finally{ try { writer.flush(); writer.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } ------------------------------华丽的分割线-------------------------------- package com.jing.test.thread; import java.util.List; /** * 操作打印线程类的主类 * @author jtj * */ public class ExecuteRun implements Runnable { //将打印线程的类装到该集合中 List<Runnable> threadList ; public ExecuteRun(List<Runnable> list) { this.threadList = list ; } @Override public void run() { int size = threadList.size() ; for(int i = 0; i < size; i++){ Runnable runnable = threadList.get(i) ; Thread printThread = new Thread(runnable) ; printThread.start(); try { //等待该线程完成再往下执行 printThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } } --------------------------------------华丽的分割线---------------------------------------- package com.jing.test.thread; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; public class MainRun { public static void main(String[] args){ String[] aCodes = {"A","B","C","D"} ; String[] bCodes = {"B","C","D","A"} ; String[] cCodes = {"C","D","A","B"} ; String[] dCodes = {"D","A","B","C"} ; new Thread(new ExecuteRun(MainRun.addCollections(aCodes, "src/com/jing/resources/a.txt"))).start() ; new Thread(new ExecuteRun(MainRun.addCollections(bCodes, "src/com/jing/resources/b.txt"))).start() ; new Thread(new ExecuteRun(MainRun.addCollections(cCodes, "src/com/jing/resources/c.txt"))).start() ; new Thread(new ExecuteRun(MainRun.addCollections(dCodes, "src/com/jing/resources/d.txt"))).start() ; } /** * 装打印线程集合方法 * @param codes 打印线程的先后顺序数组 * @param filename 输出的文件名 * @return */ public static List<Runnable> addCollections(String[] codes,String filename){ List<Runnable> list = new ArrayList<>() ; int size = codes.length ; for(int i = 0; i < size; i++){ Runnable runnable = new PrintRun(codes[i], filename) ; list.add(runnable) ; } return list ; } }
A_finder 2016-03-25
  • 打赏
  • 举报
回复
希望大家能够提供不同的解法。 如果还有其他的多线程编程题,请贴上来,大家共同探讨。
A_finder 2016-03-25
  • 打赏
  • 举报
回复
今天又想了好久,想出一种解法,贴上代码,请大家指教。

package com;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Problem {
	public void appendMethod(String fileName, String content) {
		try {
			// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
			FileWriter writer = new FileWriter(fileName, true);
			writer.write(content);
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	public static void main(String[] args) {
		String A = "A";
		String B = "B";
		String C = "C";
		String D = "D";
		String[] contexts = new String[4];
		contexts[0] = A;
		contexts[1] = B;
		contexts[2] = C;
		contexts[3] = D;
		String pre = "E:\\thread\\";
		String suf = ".txt";
		String[] fileNames = new String[4];
		List<ArrayBlockingQueue<String>> queues = new ArrayList<ArrayBlockingQueue<String>>();
		//数组有泛型问题,不好用。
		// ArrayBlockingQueue<?>[] queues = new ArrayBlockingQueue<?>[4];
		for (int i = 0; i < contexts.length; i++) {
			String fileName = pre + contexts[i] + suf;
			fileNames[i] = fileName;
			ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(
					contexts.length);
			try {
				queue.put(fileName);
			} catch (InterruptedException e) {
			}
			queues.add(queue);
		}
		for (int i = 0; i < contexts.length; i++) {
			ArrayBlockingQueue<String> producet;
			if ((i + 1) == contexts.length) {
				producet = queues.get(0);
			} else {
				producet = queues.get(i + 1);
			}
			new Thread(new R(contexts[i], producet, queues.get(i))).start();
		}
	}
}

class R implements Runnable {
	String context;
	BlockingQueue<String> producet;
	BlockingQueue<String> consumer;
	public R(String context, BlockingQueue<String> producet,
			BlockingQueue<String> consumer) {
		this.context = context;
		this.producet = producet;
		this.consumer = consumer;
	}
	public void run() {
		try {
			Problem p = new Problem();
			for (int i = 0; i < 100; i++) {
				String fileName = consumer.take();
				p.appendMethod(fileName, context);
				producet.put(fileName);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}
}
ddyouyue 2016-03-25
  • 打赏
  • 举报
回复
java.util.concurrent.CountDownLatch
me阿木 2016-03-25
  • 打赏
  • 举报
回复
不知道题主有没有注意到每个文件里的输出都是有序的。这涉及到线程控制了,通过线程控制使无序的多线程实现有序,推荐使用join()关键字。

62,614

社区成员

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

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