18

推荐

运行结果:

编辑于 2015-07-16 17:20:57

回复(11)

12

自己重写了一下推荐答案,加了些注释方便理解

package threadpackage;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.PrintWriter;

import java.util.Random;

/*

一个文件中有10000个数,用Java实现一个多线程程序将这个10000个数输出到5个不用文件中(不要求输出到每个文件中的数量相同)。

要求启动10个线程,两两一组,分为5组。

每组两个线程分别将文件中的奇数和偶数输出到该组对应的一个文件中,

需要偶数线程每打印10个偶数以后,就将奇数线程打印10个奇数,如此交替进行。

同时需要记录输出进度,每完成1000个数就在控制台中打印当前完成数量,并在所有线程结束后,在控制台打印”Done”.

*/

/**

* 分析:可以将10000个数分成5份,每一份(2000个数)对应一组,即两个线程,来分别输出这一份的奇数和偶数,

* 同时声明一个共享变量,用于统计当前所有线程输出的个数,反映记录的输出进度

*/

public class PrintByThread {

public static void main(String[] args) {

try {

//创建一个包含10000数字的输入文件

PrintWriter pw=new PrintWriter(new FileWriter(new File("input.txt")),true);

Random random=new Random();

for (int i = 0; i < 10000; i++) {

pw.print(Math.abs(random.nextInt())%100+",");

}

pw.flush();

pw.close();

//读取文件中的数字,分5次读取,每次读取2000个

BufferedReader reader=new BufferedReader(new FileReader("input.txt"));

String str=reader.readLine();

reader.close();

String[] strs=str.split(",");//将一行字符串全部解析为10000个数字

int j=0;//10000个数的索引计数

for (int i = 0; i < 5; i++) {

int records[]=new int[2000];

for (int k = 0; k < 2000; k++) {

records[k]=Integer.parseInt(strs[j]);

j++;

}

//定义输出文件

PrintWriter writer =new PrintWriter(new FileWriter(new File("output"+i+".txt")),true);

//定义实现的方法

ThreadGroup group=new ThreadGroup(records, writer);

//开启一对儿线程

new Thread(group).start();

new Thread(group).start();

}

} catch (Exception e) {

// TODO: handle exception

}

}

}

package threadpackage;

import java.io.PrintWriter;

class ThreadGroup implements Runnable{

//所有类对象共享的同一个计数器count,记录总共输出的记录总数

private static int count=0;

//所有的ThreadGroup类对象共享一个锁,用于count变量的同步,任何一个线程需要修改count变量,必须取得该锁

private static Object lock=new Object();

public static final int EVEN=0;//代表偶数

public static final int ODD=1;//代表奇数

//*********以上静态变量,属于整个类所有***********

private int type;

private int records[];

private PrintWriter writer;//每组共享一个writer,输出到同一个文件

private int oddPoint=0;//记录每次打印奇数的起始位置

private int evenPoint=0;//记录每次打印偶数的起始位置

public ThreadGroup(int[] records,PrintWriter writer){

this.records=records;

this.writer=writer;

this.type=EVEN;

}

//线程方法实现

public void run() {

while(print());

}

private synchronized boolean print(){

for(int i=0;i<10;){

//如果奇数和偶数都打印完成以后,就直接停止打印循环,等待该线程自己结束

if (oddPoint>=records.length&&evenPoint>=records.length) {

notifyAll();

return false;

}

//如果该线程该打印奇数,但奇数已经打印晚了,就直接停止本次10个数的打印,

//同理偶数,等下次切换打印类型后,再开始打印另外一种类型

if ((oddPoint>=records.length&&type==ODD)||(evenPoint>=records.length&&type==EVEN)) {

break;

}

//判断开始打印偶数

if (type==EVEN) {

if (records[evenPoint]%2==0) {

i++;

writer.print(records[evenPoint]+",");

writer.flush();

//锁定全局变量方便线程输出后计数

synchronized (lock) {

count++;

if (count%1000==0) {

System.out.println("当前完成数量:"+count);

if (count==10000) {

System.out.println("Done!");

}

}

}

}

//无论是否是偶数,打印成功一个后,偶数的起始位置都要后移

evenPoint++;

}else {

//打印奇数

if (records[oddPoint]%2==1) {

i++;

writer.print(records[oddPoint]+",");

writer.flush();

//锁定全局变量方便线程输出后计数

synchronized (lock) {

count++;

if (count%1000==0) {

System.out.println("当前完成数量:"+count);

if (count==10000) {

System.out.println("Done!");

}

}

}

}

//无论是否是奇数,打印成功一个后,偶数的起始位置都要后移

oddPoint++;

}

}

type=~type;//切换打印类型

notifyAll();//一组中的任一线程打印完后唤醒另一个线程

try {

wait();//释放锁进入等待状态,等待另一线程打印

} catch (Exception e) {

// TODO: handle exception

}

return false;

}

}

发表于 2016-03-19 00:04:25

回复(9)

10

网易笔试估计过不去了。。。

发表于 2016-03-21 19:05:04

回复(6)

1

package interviewquestion;

import java.io.*;

import java.util.concurrent.ConcurrentLinkedQueue;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.atomic.AtomicBoolean;

import java.util.concurrent.atomic.AtomicInteger;

public class WorkQueue {

private ConcurrentLinkedQueue oddQueue = new ConcurrentLinkedQueue();

private ConcurrentLinkedQueue evenQueue = new ConcurrentLinkedQueue();

private AtomicBoolean isClose = new AtomicBoolean(false);

private AtomicInteger workCount = new AtomicInteger(0);

private ExecutorService service;

private CountDownLatch latch;

private PrintWriter writer;

private int threads;

private int targets = 10000;

public WorkQueue(ExecutorService service, int threads, CountDownLatch latch) {

this.service = service;

this.threads = threads;

this.latch = latch;

}

public void doWork() throws IOException {

service.execute(new Producer());

writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream("result.txt")));

for(int i = 0; i < threads; i++) {

Worker evenWorker = new Worker(evenQueue, true);

Worker oddWorker = new Worker(oddQueue, false).setCoWorker(evenWorker);

service.execute(evenWorker);

service.execute(oddWorker);

}

/*用于模拟输入

for(int i = 1; i <= targets; i++) {

if(i % 2 == 0) {

evenQueue.add(i);

} else {

oddQueue.add(i);

}

}*/

}

private void writeToFile(Integer integer) throws IOException {

writer.print(integer.intValue() + "\n");

int current = workCount.incrementAndGet();

if(current % 1000 == 0) {

System.out.println("当前完成数:" + current);

}

if(current >= targets) {

isClose.set(true);

System.out.println("done");

}

}

public void close() {

writer.flush();

writer.close();

service.shutdown();

}

private class Worker implements Runnable {

private AtomicBoolean doWork;

private Worker coWorker;

private ConcurrentLinkedQueue works;

public Worker(ConcurrentLinkedQueue works, boolean doWork) {

this.doWork = new AtomicBoolean(doWork);

this.works = works;

}

public boolean isClose() {

return isClose.get() && works.isEmpty();

}

public Worker setCoWorker(Worker coWorker) {

this.coWorker = coWorker;

coWorker.coWorker = this;

return this;

} [@Override](/profile/992988) public void run() {

try {

while(!isClose()) {

if(doWork.get()) {

for(int count = 0; count < 10 && !isClose();) {

Integer num = works.poll();

if(num != null) {

writeToFile(num);

count++;

}

}

doWork.set(false);

coWorker.doWork.set(true);

}

}

} catch (Exception e) {} finally {

latch.countDown();

}

}

}

public class Producer implements Runnable { [@Override](/profile/992988) public void run() {

BufferedReader reader = null;

try {

reader = new BufferedReader(new FileReader("input.txt"));

String line = reader.readLine();

int temp;

for(String string : line.split(" ")) {

temp = Integer.parseInt(string);

if(temp % 2 == 0) {

evenQueue.add(temp);

} else {

oddQueue.add(temp);

}

}

} catch (Exception e) {}

finally {

if(reader != null) {

try {

reader.close();

} catch (Exception e) {}

}

}

}

}

public static void main(String[] args) {

int threads = 10;

CountDownLatch latch = new CountDownLatch(threads);

WorkQueue workQueue = null;

try {

ExecutorService executor = Executors.newFixedThreadPool(threads);

workQueue = new WorkQueue(executor, threads, latch);

workQueue.doWork();

latch.await();

} catch (Exception e) {}

finally {

if(workQueue != null) {

workQueue.close();

}

}

}

}

编辑于 2017-12-16 16:21:27

回复(0)

1

package first;

import java.io.File;

import java.io.PrintWriter;

import java.net.URL;

import java.util.ArrayDeque;

import java.util.Queue;

import java.util.Scanner;

public class Solve

{

public static void main(String[] args) throws Exception

{

URL url = CreateData.class.getResource("/data.txt");

Scanner scanner = new Scanner(new File(url.toURI()));

for (int i = 0; i < 10000; i++)

{

int data = Integer.parseInt(scanner.nextLine());

if (data % 2 == 0)

{

Common.ou.add(data);

} else

{

Common.ji.add(data);

}

}

scanner.close();

Thread[] threads =new Thread[10];

for (int i = 0; i < 5; i++)

{

PrintWriter pw = new PrintWriter(new File("./data"+i+".txt"));

Common common=new Common();

threads[i*2] = new Thread(new WriterJi(pw,common));

threads[i*2+1] = new Thread(new WriterOu(pw,common));

}

for (Thread thread : threads)

{

thread.start();

}

}

}

class Common

{

//每组打印线程奇偶打印标志

public volatile boolean isJi = false;

private static int count = 0;

public static Queue ji = new ArrayDeque<>(10000);

public static Queue ou = new ArrayDeque<>(10000);

public static synchronized Integer jiGet()

{

inc();

if (!ji.isEmpty())

{

return ji.poll();

} else

{

return null;

}

}

public static synchronized Integer ouGet()

{

inc();

if (!ou.isEmpty())

{

return ou.poll();

} else

{

return null;

}

}

public static synchronized void inc()

{

if(++count %1000 ==0)

{

System.out.println(count);

}

if(count == 10000)

{

System.out.println("Done");

}

}

}

class WriterJi implements Runnable

{

public PrintWriter pw;

private int count = 0;

private Common common;

public WriterJi(PrintWriter pw,Common common)

{

this.pw = pw;

this.common= common;

}

@Override

public void run()

{

while (!Common.ji.isEmpty() || !Common.ou.isEmpty())

{

if (common.isJi == true)

{

while (++count <= 10)

{

Integer data =Common.jiGet();

if(data != null)

{

pw.println(data);

}

else

{

break;

}

}

pw.flush();

count = 0;

common.isJi = false;

}

}

}

}

class WriterOu implements Runnable

{

private PrintWriter pw;

private int count = 0;

private Common common;

public WriterOu(PrintWriter pw,Common common)

{

this.pw = pw;

this.common =common;

}

@Override

public void run()

{

while (!Common.ji.isEmpty() || !Common.ou.isEmpty())

{

if (common.isJi == false)

{

while (++count <= 10)

{

Integer data =Common.ouGet();

if(data != null)

{

pw.println(data);

}

else

{

break;

}

}

pw.flush();

count = 0;

common.isJi = true;

}

}

}

}

编辑于 2017-07-19 20:36:21

回复(0)

1

测试代码:

编辑于 2015-04-01 14:46:48

回复(0)

0

import java.io.*;

import java.util.Random;

public class multiThreadPrint {

private static final String path = "E:\\JavaBook\\MyprojectTouTiao\\MyAlgorithms\\fileprint\\";

//一个文件中有10000个数,

// 用Java实现一个多线程程序将这个10000个数输出到5个不用文件中(不要求输出到每个文件中的数量相同)。

// 要求启动10个线程,两两一组,分为5组。

// 每组两个线程分别将文件中的奇数和偶数输出到该组对应的一个文件中,

// 需要偶数线程每打印10个偶数以后,就将奇数线程打印10个奇数,如此交替进行。

// 同时需要记录输出进度,每完成1000个数就在控制台中打印当前完成数量,

// 并在所有线程结束后,在控制台打印”Done”.

public static void main(String[]args)

{

try {

PrintWriter pw = new PrintWriter(new FileWriter(new File(path+"input.txt")),true);

Random random = new Random();

for(int i =0;i<10000;i++)

{

pw.print(Math.abs(random.nextInt())%100+" ");

}

pw.flush();

pw.close(); //输出10000个数到文件中。

BufferedReader reader = new BufferedReader(new FileReader(path+"input.txt"));

String str = reader.readLine();

reader.close();

String []strs = str.split(" ");

int j =0;

for(int i=0;i<5;i++)

{

int []records = new int [2000];

for(int k=0;k<2000;k++)

{

records[k] = Integer.parseInt(strs[j]);

j++; //读入每一个字符。数字

}

PrintWriter writer = new PrintWriter(new FileWriter(new File(path+"output"+i+".txt")), true);

myThreadGroup group = new myThreadGroup(records, writer);

new Thread(group).start();

new Thread(group).start();

}

}

catch (FileNotFoundException e)

{

e.printStackTrace();

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

class myThreadGroup implements Runnable{

private static int count = 0;

private static Object lock = new Object();

public static final int EVEN = 0;

public static final int ODD = -1;

//myThreadGroup成员变量ODD应该是-1,代码的type=~type 0按位取反应该是-1;1的话break的条件不能成立,容易造成边界溢出

//Exception in thread "Thread-3" java.lang.ArrayIndexOutOfBoundsException: 2000

// at InterviewDirectory.netEASe2017.myThreadGroup.print(multiThreadPrint.java:116)

// at InterviewDirectory.netEASe2017.myThreadGroup.run(multiThreadPrint.java:83)

// at java.lang.Thread.run(Thread.java:748)

private int type;

private int records[];

private PrintWriter writer;

private int oddPoint = 0;

private int evenPoint = 0;

public myThreadGroup(int [] records, PrintWriter writer) {

this.records = records;

this.writer = writer;

this.type = EVEN;

}

public void run()

{

while (print()); //两个线程进来之后会一直循环,直到循环输出2000个数字为止。

}

private synchronized boolean print() {

for(int i =0;i<10;)

{

if(oddPoint>=records.length&&evenPoint>=records.length)

{

notifyAll();

return false;

}

if((oddPoint>=records.length&&type==ODD)||(evenPoint>=records.length&&type==EVEN))

break;

if(type==EVEN)

{

if(records[evenPoint]%2==0)

{

i++;

writer.print(records[evenPoint]+" ");

writer.flush();

synchronized (lock)

{

count++;

if(count%1000==0)

{

System.out.println("当前完成量:"+count);

if(count==10000)

System.out.println("Done!");

}

}

}

evenPoint++;

}else {

if(records[oddPoint]%2==1)

{

i++;

writer.print(records[oddPoint]+" ");

writer.flush();

synchronized (lock)

{

count++;

if(count%1000==0)

{

System.out.println("当前完成量:"+ count);

if(count==10000)

{

System.out.println("Done!");

}

}

}

}

oddPoint++;

}

}

type=~type;

notifyAll();

try {

wait();

}catch (InterruptedException e)

{

e.printStackTrace();

}

return true;

}

}

发表于 2018-05-11 15:49:46

回复(0)

0

很多答案结果展示的不够完整,本人认为总共10000个数同步的分别放入多个文件是很重要的一点,这里是双线程,第一个跑了5037,第二个跑了4963.。。。我看很多代码符合题意,但不是等于题意,是题意所述情况的一个特殊情况。

package java_offer;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStreamWriter;

publicclassQ22 {

public Integer sum = 10000;

public Object lock=new

Object();

boolean[]

light

= {true,true};

public

static

void

open(Q22 c,String addr,String addr2){

odd od1 = c.new odd();

even ev1 = c.new even();

od1.setsDestFile(addr);

ev1.setsDestFile(addr);

od1.setTag("odd"+"

"+"tag1");

ev1.setTag("even"+"

"+"tag1");

odd od2 = c.new odd();

even ev2 = c.new even();

od2.setsDestFile(addr2);

ev2.setsDestFile(addr2);

od2.setTag("odd"+"

"+"tag2");

ev2.setTag("even"+"

"+"tag2");

od1.id = 0;

od2.id = 1;

ev1.id = 0;

ev2.id = 1;

od1.start();

od2.start();

ev1.start();

ev2.start();

}

public

static

void

main(String[] args) throws IOException{

Q22 c = new Q22();

open(c,"./data/1.txt","./data/2.txt");

}

publicstaticsynchronizedvoid

writeByFileOutputStream

(String _sDestFile,

String _sContent) throws IOException {

FileOutputStream fos = null;

File destFile = new File(_sDestFile);

BufferedWriter out = null;

try {

out = new BufferedWriter(new

OutputStreamWriter(

new FileOutputStream(destFile, true)));

out.write(_sContent+"\r\n");

} catch (Exception e) {

e.printStackTrace();

}finally{

try {

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

class odd extends Thread{

String sDestFile;

String tag;

int

id;

public String getTag() {

return

tag

;

}

public

void

setTag(String tag) {

this.tag = tag;

}

public String getsDestFile() {

return

sDestFile;

}

public

void

setsDestFile(String sDestFile) {

this.sDestFile = sDestFile;

}

int

num = 10;

@Override

publicvoid

run

() {

// TODO Auto-generated method stub

while(true){

synchronized(

lock

){

if(sum<=0){

break;

}

else

if(light[id]){

StringBuffer sb = new StringBuffer();

if(sum%1000 == 0){

System.out.println((10000-sum)

+ " has been done!");

}

sb.append(sum--);

sb.append(tag);

try {

writeByFileOutputStream(sDestFile,

sb.toString());

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if(--this.num == 0

){

light[id] = false;

this.num = 10;

lock.notifyAll();

try {

Thread.sleep(10);

lock.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

else

if(!light[id]){

lock.notifyAll();

try {

Thread.sleep(10);

lock.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

}

}

class even extends Thread{

String sDestFile;

String tag;

int

id;

public String getTag() {

return

tag

;

}

public

void

setTag(String tag) {

this.tag = tag;

}

public String getsDestFile() {

return

sDestFile;

}

public

void

setsDestFile(String sDestFile) {

this.sDestFile = sDestFile;

}

int

num = 10;

@Override

publicvoid

run

() {

// TODO Auto-generated method stub

while(true){

synchronized(

lock

){

if(sum<=0){

break;

}

else

if(!light[id]){

StringBuffer sb = new StringBuffer();

if(sum%1000 == 0){

System.out.println((10000-sum)

+ " has been done!");

}

sb.append(sum--);

sb.append(tag);

try {

writeByFileOutputStream(sDestFile,

sb.toString());

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if(--this.num == 0

){

light[id] = true;

this.num = 10;

lock.notifyAll();

try {

Thread.sleep(10);

lock.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

else

if(!light[id]){

lock.notifyAll();

try {

Thread.sleep(10);

lock.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

}

}

}

发表于 2017-02-20 14:00:27

回复(1)

0

package com.sort.main;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.ArrayList;

import java.util.List;

public class ThreadFileDemo {

public static void main(String[] args){

String filename = "a.txt";

String toFile = "b.txt";

PrintWriter print = null;

FileWriter fw = null;

List data = new ArrayList();

//产生随机数

for(int i = 0; i < 10000; i++){

data.add((int)(Math.random() * 1000));

}

//写入文件

try {

fw = new FileWriter(filename);

fw.write(data.toString());

fw.close();

} catch (IOException e) {

e.printStackTrace();

}

try {

print = new PrintWriter(new FileWriter(toFile));

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

String str = data.toString().substring(1, data.toString().length() - 1);

NumResource r = new NumResource(str.split(", "), print);

ThreadOdd odd = new ThreadOdd(r);

ThreadEven even = new ThreadEven(r);

Thread t1 = new Thread(odd);

Thread t2 = new Thread(odd);

Thread t3 = new Thread(odd);

Thread t4 = new Thread(odd);

Thread t5 = new Thread(odd);

Thread t6 = new Thread(even);

Thread t7 = new Thread(even);

Thread t8 = new Thread(even);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

t6.start();

t7.start();

t8.start();

}

}

class NumResource{

public String[] str;

public int count;

public int o;

public int e;

public int s;

public boolean flag = false;

public PrintWriter print = null;

public NumResource(String[] str, PrintWriter print){

this.str = str;

this.print = print;

count = str.length;

}

//奇数计数

public synchronized void odd(){

while(flag){

try {

wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

for(int i = 0; i < 10;){

if(s >= count){

if(print != null){

print.close();

}

System.out.println("Done");

System.exit(0);

}

//如果奇数打印完毕,直接跳出

if(o >= count){

break;

}

if(Integer.parseInt(str[o]) % 2 != 0){

i++;

//System.out.println("奇数:" + str[o] + "-" + s);

print.write(str[o] + "\n");

print.flush();

printCount(o);

}

o++;

}

flag = true;

notifyAll();

}

//偶数计数

public synchronized void even(){

while(!flag){

try {

wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

for(int i = 0; i < 10;){

//结束关闭流,退出

if(s >= count){

if(print != null){

print.close();

}

System.out.println("Done");

System.exit(0);

}

//如果偶数打印完毕,直接跳出

if(e >= count){

break;

}

if(Integer.parseInt(str[e]) % 2 == 0){

i++;

//System.out.println("偶数:" + str[e] + "-" + s);

print.write(str[e] + "\n");

print.flush();

printCount(e);

}

e++;

}

flag = false;

notifyAll();

}

public synchronized void printCount(int n){

s++;

if(s % 1000 == 0){

System.out.println(Thread.currentThread().getName() + "完成打印个数:"+ s);

}

}

}

class ThreadOdd implements Runnable{

private NumResource r;

ThreadOdd(NumResource r){

this.r = r;

}

@Override

public void run() {

while(true)

{

r.odd();

}

}

}

class ThreadEven implements Runnable{

private NumResource r;

ThreadEven(NumResource r){

this.r = r;

}

@Override

public void run() {

while(true)

{

r.even();

}

}

}

发表于 2016-08-23 12:55:08

回复(0)

0

package Chapter1;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.concurrent.atomic.AtomicInteger;

import java.util.concurrent.locks.ReentrantLock;

public class Main03

{

public static void main(String ...args) throws Exception

{

Main03 ob = new Main03();

ob.prepareTest();

BufferedReader br = new BufferedReader(new FileReader("E:/input.txt"));

String str = br.readLine();

br.close();

String[] tokens = str.split(" ");

for(int i = 0;i < 5;i++)

{

int[] records = new int[2000];

PrintWriter pw = new PrintWriter(new FileWriter("E:/output" + i + ".txt"));

for(int j = 0;j < 2000;j++)

{

records[j] = Integer.parseInt(tokens[i*2000 + j]);

}

ThreadGroup tg = new ThreadGroup(pw,records);

new Thread(tg).start();

new Thread(tg).start();

}

}

private void prepareTest()

{

File inputFile = new File("E:/input.txt");

FileWriter f = null;

PrintWriter pw = null;

try

{

f = new FileWriter(inputFile);

pw = new PrintWriter(f);

for(int i = 0;i < 10000;i++)

{

pw.write(i + " ");

}

pw.flush();

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

finally

{

if(f != null && pw != null)

{

try

{

f.close();

pw.close();

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

}

}

class ThreadGroup implements Runnable

{

//10 threads shared

private static AtomicInteger totalNumbers = new AtomicInteger(0);

//2 threads in the same group shared

private PrintWriter pw;

private ReentrantLock groupLock = new ReentrantLock();

private volatile int type = 0; //0 for even thread,-1 for odd thread

private int oddPoint = 0;

private int evenPoint = 0;

private int[] toPrint;

public ThreadGroup(PrintWriter writer,int[] numbers)

{

pw = writer;

toPrint = numbers;

}

@Override

public void run()

{

try {

while(doPrint());

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

private boolean doPrint() throws InterruptedException

{

try

{

groupLock.lock();

//print 10 numbers

int recordsNum = toPrint.length;

for(int i = 0;i < 10;i++)

{

if(evenPoint >= recordsNum && oddPoint >= recordsNum)

{

return false;

}

if(evenPoint >= recordsNum && type == 0 || oddPoint >= recordsNum && type == 1)

break;

//print even numbers

if(type == 0)

{

while(evenPoint < recordsNum && toPrint[evenPoint] %2 != 0)

evenPoint ++;

if(evenPoint >= recordsNum)

{

break;

}

pw.write(toPrint[evenPoint] + ",");

evenPoint++;

pw.flush();

int number = totalNumbers.incrementAndGet();

if(number % 1000 == 0)

System.out.println("Processed " + number + " tokens!");

}

else

{

while(oddPoint < recordsNum && toPrint[oddPoint] %2 == 0)

oddPoint ++;

if(oddPoint >= recordsNum)

{

break;

}

pw.write(toPrint[oddPoint] + ",");

oddPoint++;

pw.flush();

int number = totalNumbers.incrementAndGet();

if(number % 1000 == 0)

System.out.println("Processed " + number + " tokens!");

}

}

type = ~type;

return true;

}

finally

{

groupLock.unlock();

}

}

}

感觉这个题目好绕,我来个抛砖引玉吧~~

以上代码只做了简单的测试,不保证正确。

看到题目,首先想到的是把数据均分为5组,然后每组里面奇偶线程交替打印。要注意的是10个线程互斥访问总的计数器,并且每组里面的两个线程使用的是同一个流,所以要进行同步;简单写了一个,效率什么的肯定不行,主要是思路拿出来让大神们指点一下。

另外,其实题目并没有要求把数据平均地打印到5个输出文件中,所以感觉应该可以用forkjoin线程池来做,不过同一个组里面奇偶线程同步访问的问题是绕不开的,这个应该也是主要出错的地方。

发表于 2016-08-02 16:39:14

回复(0)

0

package thread;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.BufferedReader;

import java.io.PrintWriter;

import java.util.Arrays;

import java.util.Random;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class FileMultiThread {

private static final CountDownLatch door = new CountDownLatch(10); //同步工具类,可以确保n个线程的同步

public static void main(String[] args) {

FileMultiThread fmt = new FileMultiThread();

try {

PrintWriter writer = new PrintWriter(new FileWriter("F:\\number.txt"));

Random random = new Random();

for(int i = 0; i < 10000; i++){

writer.print(random.nextInt(10000)+",");

}

writer.flush();

writer.close();

BufferedReader reader = new BufferedReader(new FileReader("F:\\number.txt"));

String numberString = reader.readLine();

reader.close();

String[] strArrays = numberString.split(",");

int step = 2000;

for(int i = 0; i < 5; i++){

int from = i * step;

int to = (i + 1) * step;

String[] records = Arrays.copyOfRange(strArrays, from,

to);   //复制数组,有范围的复制,范围 from <= x < to

PrintWriter pw = new PrintWriter(new

FileWriter("F:\\test"+ i + ".txt"));

//                PrintWriter pw1 = new PrintWriter(new BufferedWriter(

//                        new OutputStreamWriter(new FileOutputStream("F:\\summary.txt"),"GBK")));

final outPutToFile opt = new outPutToFile(pw, records); //虽然五次循环下的CopyOfPrintTest1

//对象的名称相同,但因为五个对象的内容不同,所以这五个对象的引用是不同的,所以jvm在内存中

//会开辟五个独立的内存用来分别存储对象

fmt.odd(opt);

fmt.even(opt);

} //for结束

door.await(); //通过使用CountDownLatch来实现10个线程的同步。通过调用await()方法可以在所有线程结束之后打印"Done"

//每当主线程获取时间片,准备打印“Done”时,都会因为十个子线程尚未全部执行结束而被阻塞,直到十个子线程全部执行

//完毕(即死亡)而从改行恢复执行

System.out.println("Done");

} catch (Exception e) {

e.printStackTrace();

}

}

public void odd(final outPutToFile opt){

new Thread(new Runnable(){

@Override

public void run() {

while(opt.printOdd()){

}

door.countDown();  //每当线程结束,便调用CountDownLatch类的方法countDown()减1,当减到

//0时,即说明子线程全部执行结束,主线程可以执行下一步的代码

}

}).start();

}

public void even(final outPutToFile opt){

new Thread(new Runnable(){

@Override

public void run() {

while(opt.printEven()){

}

door.countDown();

}

}).start();

}

}

class outPutToFile{

private PrintWriter out = null;

private String[] records;

private static int count = 0; //静态变量(一个类只有一个),用来记录有效的输出次数

private boolean flag = true;  //全局变量,用来控制奇偶线程的执行,为true时,执行奇线程,为false时,执行偶线程

private Lock lock = new ReentrantLock(); //奇偶线程共享同一把锁

/**

* 题目要求先打印10个奇数,再打印10个偶数,因此设置两个条件对象(更加灵活)。

* oddCondition下有三种情况:

*        1、当flag为false时,奇线程阻塞,偶线程执行;

*        2、当flag为true,且打印了10个奇数时,则偶线程唤醒,奇线程阻塞,偶线程执行;

*        3、当flag为true,但剩余奇数个数已不够时,则for循环结束,唤醒偶线程,继而当前线程结束

* evenCondition下有三种情况:

*        1、当flag为true时,偶线程阻塞,奇线程执行;

*        2、当flag为false,且打印了10个偶数时,则奇线程唤醒,偶线程阻塞,奇线程执行;

*        3、当flag为false,但剩余偶数个数已不够时,则for循环结束,唤醒奇线程,继而当前线程结束

*/

private Condition oddCondition = lock.newCondition();  //条件对象之奇数对象

private Condition evenCondition = lock.newCondition(); //条件对象之偶数对象

/**

* 问题:若数组中的2000个数,只有三个奇数,剩下的全是偶数,会发生什么情况?

* 思考:奇线程很快就会结束,只剩下偶线程。这时,如果偶线程在打印10个偶数后,将自己阻塞并尝试唤醒奇线程,

* 会发生什么?奇线程无法唤醒(已死亡),自己(偶线程)被阻塞,无法被唤醒,其任务永远无法继续下去,程序

* 出错。

* 设想:当奇/偶线程循环结束时,在另一个线程中使“阻塞自己,唤醒对方”的代码失效,一直循环执行,直到循环结束。

* 方案:记录奇/偶线程的循环次数。以奇线程为例,在奇线程中判断wholeEvenStep的值是否小于数组的长度,若小于,则说明对

* 方线程还没死亡,执行“阻塞自己,唤醒对方”的代码;否则,不执行,继续下一次循环。偶线程的操作同上。

*/

private int wholeOddStep = 0; //用来记录奇线程执行的次数

private int wholeEvenStep = 0; //用来记录偶线程执行的次数

private static int array_length = 0;  //将数组的长度设置为静态变量

public outPutToFile(PrintWriter out,String[] records){

this.out = out;

this.records = records;

outPutToFile.array_length = records.length; //动态设置数组的长度

}

/**

* 奇线程要执行的函数

* @return

*/

public boolean printOdd(){

lock.lock(); //上锁,必须加上try/finally,以确保锁会被释放

int oddStep = 0; //记录奇线程有效的打印次数

boolean oddFlag = true; //设置函数返回值

try {

/**

* 之前用的是if(!flag){oddCondition.await();} else{...} ... 的形式,

* 这种用法的错误之处在于,当flag为false时,奇线程会进入阻塞状态;当其对应的偶线程将

* flag的值修改为true,并且唤醒奇线程时。奇线程便从阻塞的地方醒来,继续执行。结果就是

* 执行完if(...)中的代码后,并不会进入else中(虽然flag已为true),而是进行else

* 之后的代码。错误由此产生。

* 使用while(!flag){...}循环的好处在于,当奇线程从阻塞的地方醒来后,将继续循环执行,

* 如此,偶线程修改后的flag便会被检测出已为true,不符合当前条件,循环结束,进入之后真正

* 要执行的代码

*/

while(!flag){

oddCondition.await();

}

for(int i = 0; i < array_length; i++){

wholeOddStep = i;

int num = Integer.parseInt(records[i]);

if(num % 2 == 1){  //如果是奇数,则打印

out.print(num+",");

out.flush();

synchronized (outPutToFile.class) { //10个线程共用一个count,必须加锁保护,使其原子操作

count++;

if(count % 1000 == 0){ //每当打印1000个数时,则提示当前的数量

System.out.println("当前完成数量:" + count);

}

}

oddStep++; //加1

if((wholeEvenStep + 1) < array_length){ //奇线程若未死亡,则执行以下代码,否则不执行

if(oddStep % 10 == 0){  //每打印10个奇数,则唤醒偶线程,并阻塞自己

flag = false;

evenCondition.signal();

oddCondition.await();

}

}

}

}

flag = false;

evenCondition.signal(); //循环正常结束后,唤醒偶线程

} catch (Exception e) {

e.printStackTrace();

}finally{

lock.unlock();

}

oddFlag = false; //如果printOdd()执行结束,则说明调用这个方法的线程也即将结束

closeOut(wholeEvenStep,wholeOddStep);

return oddFlag;

}

/**

* 如果奇偶线程均执行完,则关闭输出流

* @param wholeEvenStep

* @param wholeOddStep

*/

public void closeOut(int wholeEvenStep,int wholeOddStep){

if((wholeEvenStep == array_length) && (wholeOddStep == array_length)){

out.close();

}

}

/**

* 偶线程调用的方法

* @return

*/

public boolean printEven(){

lock.lock();

int evenStep = 0;

boolean evenFlag = true;

try {

while(flag){

evenCondition.await();

}

for(int i = 0; i < array_length; i++){

wholeEvenStep = i;

int num = Integer.parseInt(records[i]);

if(num % 2 == 0){

out.print(num+",");

out.flush();

synchronized (outPutToFile.class) {

count++;

if(count % 1000 == 0){

System.out.println("当前完成数量:" + count);

}

}

evenStep++;

if((wholeOddStep + 1) < array_length){

if(evenStep % 10 == 0){

flag = true;

oddCondition.signal();

evenCondition.await();

}

}

}

}

flag = true;

oddCondition.signal();

} catch (Exception e) {

e.printStackTrace();

}finally{

lock.unlock();

}

evenFlag = false; //如果printEven()执行结束,则说明调用这个方法的线程也即将结束

closeOut(wholeEvenStep,wholeOddStep);

return evenFlag;

}

}

发表于 2016-07-19 19:52:31

回复(0)

0

package thread;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PushbackReader;

import java.nio.CharBuffer;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Iterator;

import java.util.List;

import java.util.concurrent.CopyOnWriteArrayList;

public class FileTest {

public static void main(String[] args) {

File file=new

File("D:"+File.separator+"text.txt");

if(file.length()

System.out.println("文件内容长度过大!");

return;

}

char[] charBuffer=new char[(int) file.length()];

FileReader fileReader;

try {

fileReader = new FileReader(file);

fileReader.read(charBuffer);

} catch (FileNotFoundException e) {

e.printStackTrace();

}catch (IOException e) {

e.printStackTrace();

}

List list=getNumber(charBuffer);

for(int i=0;i<5;i++){

File fileIn=new

File("D:"+File.separator+"in"+(i+1)+".txt");

if(!fileIn.exists()){

try { fileIn.createNewFile(); } catch

(IOException e) {

e.printStackTrace(); }

}

try{

FileWriter fileWriter=new

FileWriter(fileIn,true);

PrintNum p=new PrintNum(list, fileWriter);

Runnable even=new evenThread(p);

Runnable odd=new oddThread(p);

Thread t1=new Thread(even);

Thread t2=new Thread(odd); t1.start();

t2.start();

} catch (IOException e) {

e.printStackTrace(); } }

try { Thread.sleep(2000); } catch

(InterruptedException e) {                 e.printStackTrace(); }

System.out.println("Done!");

}

public static List getNumber(char[] list){

List result=new

ArrayList();

Character a=null;

String a1="";

for(int i=0;i

if(list[i]!=' '){

if(list[i]=='-'){ a1="-";

}

else{ a1=a1+(list[i]-'0'); }

} else{

if(a1!=""){

result.add(Integer.valueOf(a1));

a1="";

}

}

}

if(a1!=""){

result.add(Integer.valueOf(a1));

a1="";

}

return result;

}

}

class PrintNum{

private List list;

private FileWriter fileWriter;

private int printEven=0;

private int printOdd=10;

public PrintNum(List list,FileWriter

fileWriter){

this.list=list;

this.fileWriter=fileWriter; }

public void printEven() throws IOException{

synchronized(fileWriter){

while(list.size()>0){

while(printEven>=10){

try {

fileWriter.wait();

} catch (InterruptedException e) { /

e.printStackTrace(); }

}

while(printEven<10){

printNumber(true);

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

printEven++;

}

printOdd=0;

fileWriter.notifyAll();

}

}

}

public void printOdd() throws IOException{

synchronized(fileWriter){

while(list.size()>0){

while(printOdd>=10){

try {

fileWriter.wait();

} catch (InterruptedException e) {

e.printStackTrace(); }

}

while(printOdd<10){

printNumber(false);

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

printOdd++;

}

printEven=0;

fileWriter.notifyAll();

}

}

}

private void printNumber(boolean even) throws IOException{

boolean done=false;

int i=0;

synchronized (list) {

while(i<list.size() && !done){

if(even==true &&

Math.abs(list.get(i))%2==0){

String temp=list.get(i).toString()+"

";                     fileWriter.write(temp,0,temp.length());

fileWriter.flush();

Iterator

iter=list.iterator();

for(int k=0;k<=i;k++){ iter.next();

}

iter.remove();

done=true; }

else if(even==false &&

Math.abs(list.get(i))%2==1){

String temp=list.get(i).toString()+"

";                     fileWriter.write(temp,0,temp.length());

fileWriter.flush();

Iterator

iter=list.iterator();

for(int k=0;k<=i;k++){ iter.next();

}

iter.remove();

done=true;

}

else{ i++; }

}

}

}

}

class evenThread implements Runnable {

private PrintNum p;

public evenThread(PrintNum p){ this.p=p; }

public void run() {

try { p.printEven();

} catch (IOException e) {

e.printStackTrace();

}

}

}

class oddThread implements Runnable {

private PrintNum p;

public oddThread(PrintNum p){ this.p=p; }

public void run() {

try { p.printOdd();

} catch (IOException e) {

e.printStackTrace();

}

}

}

编辑于 2015-08-28 19:26:40

回复(0)

JAVA程序中怎么看线程的个数_一个文件中有10000个数,用Java实现一个多线程程序将这...相关推荐

  1. Java 7 中 NIO.2 的使用——第四节 文件和目录

    Files类提供了很多方法用于检查在于你真正实际去操作一个文件或目录.这些方法强烈推荐,也非常有用,也能避免很多异常的发生.例如,一个很好的习惯就是在你试着移动一个文件从一个地方到另一个地方的时候,先 ...

  2. JAVA程序猿推荐看的15本书_错过了是你损失

    2019独角兽企业重金招聘Python工程师标准>>> 作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从.我想就我自己读过的技术书籍中挑 ...

  3. 为什么一个程序中变量只能定义一次_#带你学Python# 从简单程序出发理解Python基本语法

    欢迎回来. 通过上一篇文章,我们第一次触摸了Python,学会了如何用各种不同的方式运行Python的解释器.也介绍了很多工具和开发环境,是不是跃跃欲试了? 到这里,别的python教程就会从数据类型 ...

  4. java 线程状态监控_干货:教你如何监控 Java 线程池运行状态

    之前写过一篇 Java 线程池的使用介绍文章<线程池全面解析>,全面介绍了什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中, ...

  5. java 一组数据中偏差较大的数据_深入分析数据结构中的队列(java代码实现)

    不知道你有没有过在餐厅打饭的经历,我们排的队其实就是我们今天所讲的主题,我们在排队的时候,在队列头部的人打好饭离开,新来的人排在队尾.这就是入队和出队的操作.所以,队列的特性就是先进先出.有了这个概念 ...

  6. 为啥学java要看那么多东西_编程语言那么多,为啥学Java的人那么多?

    Java一直都是稳居排行榜第一的语言,在未来10年Java都会是最热门的语言之一,因为Java技术具有卓越的通用性.高效性.安全性和平台移植性,它可以跨平台的应用到不同的领域,工作需求足够大. 为什么 ...

  7. 文件在另一个程序中打开,无法删除~【删除文件被占用问题】(保姆级教程,五种解决办法~)

    一,前言 当我们操作电脑要对一个文件进行删除的时候,很多时候都会提示你说你的文件被占用,不能够删除,这个时候我们就非常的苦恼了. 二,解决办法 方法一: 这说明这个文件被打开了,我们需要将这个文件关闭 ...

  8. java接口中只能定义常量和抽象方法_接口中只能定义常量和抽象方法。( )_学小易找答案...

    [判断题]在可见光吸光光度法中,为保证吸光度测量的灵敏度,入射光始终选择 λ max. [判断题]接口中只能定义常量和抽象方法.( ) [单选题]类与对象的关系是 ( ) [单选题]某物质的摩尔吸光系 ...

  9. java sleep异常_java 注意线程下的 异常捕获,sleep(10000)休眠,可能会出现***循环...

    https://blog..net/persistencegoing/article/details/84376427 线程 (1)在catch(){} 中的语句要保证不会出现异常,或者catch中的 ...

最新文章

  1. 2022-2028年中国智慧物流行业深度调研及投资前景预测报告(全卷)
  2. 为什么要读源代码,如何阅读源代码
  3. Linux的完全免费特性
  4. 2018-2019-1 20165206 《信息安全系统设计基础》第九周学习总结
  5. go语言笔记——多值函数,本质上和nodejs的回调很像,不过nodejs是回调的第一个参数是err,而golang里是第二个!...
  6. 十个行为把你变成糟糕的程序员
  7. python爬虫知识_Python 爬虫技术分享
  8. github删除错误的commit并保留之前的提交
  9. 深入理解CPU的调度原理
  10. 在 .NET Core 中运行 JavaScript
  11. SSH2 后端编程思路总结
  12. HTML+CSS+JS实现 ❤️ html5响应式图片轮播❤️
  13. 本地也能运行AWS?是的,AWS开始进军混合云领域了
  14. 论文写作思路_2018年的16个写作思路
  15. linux如何运行python_[TimLinux] Python如何运行程序
  16. 实验四_078_刘玲志
  17. 去除tableView表头悬浮
  18. ClockworkMod Tether Alpha:避开运营商,将手机变为热点
  19. win10主题更换_WIN10好用的小软件
  20. java xml特殊字符_mybatis xml中特殊字符处理及特殊符号

热门文章

  1. TMS320F28388D 的 IPC程序使用
  2. 在找直播平台源码搭建教程?先看看这些吧
  3. linux u盘合并分区,Linux U盘分区格式化 fdisk命令
  4. 第8章 Drupal 主题系统( Drupal theme)(2) 安装主题
  5. 结构型模式中最能体现扩展性模式的是?
  6. 企业网站建设的八大种类是什么?
  7. jxr怎么变成jpg_怎么将DWG文档转成图片格式
  8. 以明道云激起高校学生运动热潮
  9. IDEA快捷键 一张图片搞定
  10. Solidworks二次开发: VC6.0创建的插件移植到VS2013中