多线程的问题,关于怎么来设计启动多线程等

黑夜中的一点慰藉 2016-03-08 09:36:22
线程用的少,请教下这样一个问题,我现在读一个文件,文件有四五千万行数据
我现在运行一个main方法来读这个文件,我想没读10万或者是100万的数据,后启动10个线程来处理这些数据,
这10个线程处理数据据的时候,main方法继续读,再读一定的值后多线程再开始处理,一直到这个文件都读完了。
这个过程中,线程这块不知道怎么来写了。请教一下。
我分析了下有下面几个问题要解决:
1、main读到一定的数据后怎来启动这10个线程,并且这10个线程取的是前面读到的数据中的不同值
(main中读到的值我是放到list中)
2、线程跑的时候,怎么继续跑这个main,数据倒是可以放到另一个list中去,然后这个list就清空,继续读文件
3、第二次,读文件到一定的数据后这个线程又怎么来运行,是启动新的线程,还是怎么搞。。。

求大神指点,有点逻辑性的代码参考就更感谢了,另外分不够了,见谅下,谢谢。
...全文
338 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
darkread 2016-03-11
  • 打赏
  • 举报
回复
引用 12 楼 wangwuyilove 的回复:
这10个线程一直检查list,这个怎么来启动线程,
伪代码如下:
void main(){
  新建10个线程对象;
  10个线程放入threadList;
  for(Thread t in threadList){
    t.start();
  }
  do{
      if(list行数<MAX_LINE){
           读取一行;
           同步(list){
              list.add(一行);
            } 
      }else{
        sleep(10);
      }
  }while(文件不空);
  打印完成信息;
  return;
}
ThreadClass extend Thread{
    execute(){
         同步(list){
            if(list.size()>0){
               取出一行;
            }
         }
         if(成果取出一行){
           计算该行数据;
           同步(结果list){
              结果list.add(该行的计算结果);
            }
          }else{
            sleep(10);
          }
    }
}
原理基本如此,也可以使用java 8 parallel stream更加简单,需要复习下lambda,你也可以看一下。
darkread 2016-03-09
  • 打赏
  • 举报
回复
这样不对吧,当list读取大于10个线程的处理时,list无限增大,必须做节制 if(list.size()>MAX_LINE){ Thread.currentThead.sleep(10); continue; } String line = lineit.next() list.add(line); 下面这个逻辑本来就是不对的,1000000hang开启动一次线程,没有必要,用我的逻辑,list有数据,10个线程分别检查到数据取出计算结果放入result_list,没有在线程sleep(10)再去检查lsit
  • 打赏
  • 举报
回复
引用 8 楼 darkread 的回复:
首先你要明确 1、10个线程是否功能一致,如果是一致,那么可以做个list,传给MyJob类,当成queue,stack完全看你程序需要了 2、线程跑的start了,main是直接返回的,main自然跑下面的代码了。 3、10个线程中每个检查list为空,10个线程挂起等有数据进来再唤醒或者直接currentThead.sleep(10)再去检查list。
10个线程的功能是一样的,但是我这要按行来解析数据,而且每行的数据字节大小不一样,是不是不能用FIleChannel.我是用的 LineIterator lineit = FileUtils.lineIterator(file,""); while(){ String line = lineit.next() list.add(line); if(lise.size%1000000 ==0){ 启动线程的 } } 这样很容易内存溢出
darkread 2016-03-09
  • 打赏
  • 举报
回复
首先你要明确 1、10个线程是否功能一致,如果是一致,那么可以做个list,传给MyJob类,当成queue,stack完全看你程序需要了 2、线程跑的start了,main是直接返回的,main自然跑下面的代码了。 3、10个线程中每个检查list为空,10个线程挂起等有数据进来再唤醒或者直接currentThead.sleep(10)再去检查list。
  • 打赏
  • 举报
回复
引用 5 楼 rickylin86 的回复:
上面的程序有问题。需要创建多个FileChannel对象来处理.不能共享同个FileChannel因为每个线程每次读取FileChannel对象的position都会变化.
谢谢,我试试
月凉西厢 2016-03-09
  • 打赏
  • 举报
回复
我觉得开一个线程池会好一些,比如newCachedThreadPool 感觉可以这样做:main线程不断的读取文件,将内容存到一个固定大小的容器中如list,当容器满了,则main阻塞,再构建一个Dispather从此容器中取数据。Dispather维护一个计数器,不断的从大容器中读取数据写入一个容量为10万行的小容器中,当读到10万行时,计数器清零,new或者从之前的空容器中得到 一个新的容器,接着继续从大容器中读取数据放入新的小容器。这样每读10万行,就Dispatch一个线程去execute就可以了
rickylin86 2016-03-09
  • 打赏
  • 举报
回复
上面的程序有问题。需要创建多个FileChannel对象来处理.不能共享同个FileChannel因为每个线程每次读取FileChannel对象的position都会变化.
  • 打赏
  • 举报
回复
这10个线程一直检查list,这个怎么来启动线程,
  • 打赏
  • 举报
回复
引用 10 楼 darkread 的回复:
这样不对吧,当list读取大于10个线程的处理时,list无限增大,必须做节制 if(list.size()>MAX_LINE){ Thread.currentThead.sleep(10); continue; } String line = lineit.next() list.add(line); 下面这个逻辑本来就是不对的,1000000hang开启动一次线程,没有必要,用我的逻辑,list有数据,10个线程分别检查到数据取出计算结果放入result_list,没有在线程sleep(10)再去检查lsit
能大概写一点代码吗,我对线程这一块不太熟悉,
rickylin86 2016-03-09
  • 打赏
  • 举报
回复
另外如果你是打算连环启动线程的话可以在MyJob类中方一个MyJob对象的实例.并且当完成后顺便启动下一个MyJob就可以了
rickylin86 2016-03-09
  • 打赏
  • 举报
回复

import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.io.IOException;

public class MyJob implements Runnable{
	
	public MyJob(FileChannel channel,long start,long end){
		this.channel = channel;
		this.start = start;
		this.end = end;
		try{
			channel.position(start);
		}catch(IOException e){
			e.printStackTrace();
			System.exit(1);
		}
		
	}

	@Override
	public void run(){
		try{
			while(channel.position() + bufSize < end){
				buf = ByteBuffer.allocate(bufSize);
				channel.read(buf);
				buf.flip();
				dates.add(buf);
			}
			buf = ByteBuffer.allocate((int)(end-channel.position()));
			channel.read(buf);
			buf.flip();
			dates.add(buf);
			finish = true;
			System.out.println(Thread.currentThread().getName() + ":完成任务.");
		}catch(IOException e){
			e.printStackTrace();
			System.exit(1);
		}
	}

	public ArrayList<ByteBuffer> getDates(){
		if(finish){
			return dates;
		}
		return null;
	}

	private FileChannel channel = null;
	private long start = 0L;
	private long end = 0L;
	private final int bufSize = 1024;
	private ByteBuffer buf = null;
	private ArrayList<ByteBuffer> dates = new ArrayList<>();
	private boolean finish = false;
}

import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
import static java.nio.file.StandardOpenOption.*;
import java.io.IOException;

public final class Test{
	public static void main(String[] args){
		String filePath = "source.bin";//设置数据源
		Path path = Paths.get(filePath);
		try(FileChannel channel = (FileChannel)(Files.newByteChannel(path,READ));){
			//设置需要启动线程的数量.
			int threadCount = 10;
			Thread[] threads = new Thread[threadCount];
			long start = 0L;
			long end = 0L;
			long contain = channel.size() / threadCount;
			for(int i = 0 ; i < threadCount ; i ++){
				start = end;
				if(i != threadCount - 1){
					end = end + contain;
				}else{
					end = channel.size();
				}
				threads[i] = new Thread(new MyJob(channel,start,end));
				threads[i].setDaemon(false);//设置为用户线程
				threads[i].start();
			}


		}catch(IOException e){
			e.printStackTrace();
			System.exit(1);
		}
	}
}
  • 打赏
  • 举报
回复
引用 1 楼 rickylin86 的回复:
不是直接定义自己的非守护线程,然后对同个文件进行读取应该就可以了吧.每个文件负责读取文件的不同部分.然后用FileChannel来处理.
不是很懂,能详细说说吗
rickylin86 2016-03-08
  • 打赏
  • 举报
回复
不是直接定义自己的非守护线程,然后对同个文件进行读取应该就可以了吧.每个文件负责读取文件的不同部分.然后用FileChannel来处理.

62,634

社区成员

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

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