多线程循环批量处理以及多线程操作文件写入相关思路

前言:这篇文章来源于我写的一个小软件:多线程批量探测指定IP段的每个IP的服务器类型(Apache,tomcat,IIS。。。)并将探测结果写入到一个文件中。那么问题来了:如何保证在IP的循环递增过程中使用多线程而每个IP不被重复使用提交(PS:当然为了避免重复,可以用线程等待,唤醒,不过我个人觉得这种方式不一定比单线程强多少)?同时,在将结果写入到文件时,怎样避免因各个线程的抢占式写入导致文件乱码?

经过了一番思考,我觉得可以这样想:对于一个循环的连续数字段,我们可以在给定线程数时,就将这一段数字平均分配给每个线程,因此每个线程只需要按步处理它的任务就行。因为没有跟其他线程的数据发生耦合,所以就可以保证每个数字都只被处理一次,同时在文件写入时也不会出现问题。

接下来,我按照这个思路写了一段测试代码,完整代码如下:

package thread;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Test1 {

	public static void main(String[] args) {
		long millis1 = System.currentTimeMillis();
		int threadNum = 5; // 测试用的线程数目
		String fileName = "C:\\Users\\Administrator\\Desktop\\测试1.txt"; // 文件名
		for (int i = 0; i < threadNum; i++) {
			MyThread myThread = new MyThread(i, threadNum, fileName);
			Thread tempThread = new Thread(myThread);
			tempThread.setName("线程" + i);
			tempThread.start();
		}

		long millis2 = System.currentTimeMillis();
		System.out.println(millis2 - millis1);  //大约1-2ms
	}

}

/**
 * 自定义线程
 * */
class MyThread implements Runnable {
	private int i; // 第几个线程
	private int threadNum; // 总共创建了几个线程
	private String fileName;  //文件名

	public MyThread(int i, int threadNum, String fileName) {
		this.i = i;
		this.threadNum = threadNum;
		this.fileName = fileName;
	}

	public void run() {
		new MyPrint().print(i, threadNum, fileName);

	}

}

/**
 * 具体的业务操作
 * */
class MyPrint {
	private BufferedWriter writer;

	public void print(int x, int threadNum, String fileName) {

		try {
			writer = new BufferedWriter(
					new FileWriter(new File(fileName), true));  //如果文件已存在则在后面追加

			for (int i = x; i <= 10000; i = i + threadNum) {
				String temp = Thread.currentThread().getName() + ": " + i
						+ "----------------------------------我是一条华丽的小尾巴";

//				System.out.println(temp);
				writer.write(temp);
				writer.newLine();
				writer.flush();
			}
			writer.close();

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

经过测试发现,虽然只用了5个线程,但是执行效率也是非常高的,1~2ms就可以全部处理完了。

附:

对于同样的写入信息,单线程的代码是这样的:

package thread;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Test {

	public static void main(String[] args) {
		long millis1 = System.currentTimeMillis();
		String fileName = "C:\\Users\\Administrator\\Desktop\\测试0.txt"; // 文件名
		try {
			BufferedWriter writer = new BufferedWriter(
					new FileWriter(new File(fileName), true));

			for(int i=0;i<=100000;i++){
				String temp = "单线程: " + i
						+ "----------------------------------我是一条华丽的小尾巴";
				writer.write(temp);
				writer.newLine();
				writer.flush();
			}
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		} 

		long millis2 = System.currentTimeMillis();
		System.out.println(millis2 - millis1);  //大约162-168ms
	}

}

经过测试,全部执行完大概需要花费160多毫秒,这个效率跟上面的多线程比起来是远远不如的O(∩_∩)O~

(PS:前言中说到的批量探测服务器类型的软件我会在后面的文章中写到,并且会放出简单的GUI界面以及源代码,敬请期待!)

时间: 2024-12-27 18:44:17

多线程循环批量处理以及多线程操作文件写入相关思路的相关文章

模态窗口其实就是在当前窗口调用系统的消息循环,响应用户的操作,将相关的消息发送到对应的窗口(转)

上周准备在公司内部转岗,面了3个部门windows客户端相关的工作,最终拿到3个Offer,主要涉及C++和Windows两大块内容,C++的题目基本都答上了,Windows一直都是我的弱项,在这里记录一下Windows相关的题目.有些答不上的问题就没列出来,还有些问题忘了,下面的答案有些大部分是我自己的理解,有些是直接从网上copy的,有问题大家可以讨论. 1:GetMessage和PeekMessage的区别? GetMessage:获取消息队列中的一个消息,存入MSG中,并从消息队列中移除

python 关于操作文件的相关模块(os,sys,shutil,subprocess,configparser)

一:os模块 os模块提供了许多允许你程序与操作系统直接交互的功能 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cd os.curdir 返回当前目录: ('.') os.pardir 获取当前目录的父目录字符串名:('..') os.makedirs('dirname1/dirname2') 可生成多层递归目录 os.removedirs('dirname1') 若目录

解决点击关闭按钮,应用程序退出时,系统爆出“集合已修改,可能无法执行枚举操作”异常的相关思路

这两天在优化升级公司的一个业务系统时,更改了一下窗体关闭事件中的一句代码,由system.Enviromen.Exit(0)改为了Application.Exit();但是这时候问题就出现了,当点击系统右上角关闭按钮的时候,会爆出“集合已修改,可能无法执行枚举操作”的异常.如下图所示: 这是什么原因造成的呢?问了一下度娘,出现“集合已修改,可能无法执行枚举操作”这种异常大部分都是因为误用foreach语句引起的,foreach是取只读的,在取的时候数据不能变(包括修改,删除,添加等).要避免这个

Python多线程循环

背景:Python脚本:读取文件中每行,放入列表中:循环读取列表中的每个元素,并做处理操作. 核心:多线程处理单个for循环函数调用 模块:threading 第一部分: :多线程脚本 (该脚本只有两个线程,t1循环次数<t2) #!/usr/bin/env python #-*- coding: utf8 -*- import sys import time import string import threading import datetime fileinfo = sys.argv[1

大数据多线程高效批量处理

工作中遇到的场景,这里写个例子出来,实际应用比此处更为健壮和完善 应用场景: 对一张表10万条数据(或100万或1亿+)进行更新操作或写入操作: 菜鸟是一条一条的执行吧,这显然不行啊 我在实际项目中是这样应用的, 批量更新!当然这显然是不够的 要线程批量更新才对吧! 怎么做呢? 举例1:10万条数据 ,我1000条1000条的处理 就是,10万/1000 = 100  , 这里我就用100个线程同时处理,每个线程负责1000条数据,这里有个关键点,处理的数据不能重复! 给个代码示例吧: 线程池中

shell练习题:使用for循环批量修改文件扩展名

shell练习题:使用for循环批量修改文件扩展名 说明:(1)在linux下批量修改文件名,将下图所示命令中的"_linux"去掉. (2)使用for循环脚本. 思路:本题的基本解题思路,先进行单个文件的改名,然后再用循环实现批量改名,这是比较常规的做法,也可以用rename专业改名工具. 方法一: 说明:使用cut.sed工具 脚本如下: #!/bin/bash cd /test for i in `ls|grep .*.jpg` do mv $i `echo $i |cut -d

使用_beginThreadex创建多线程(C语言版多线程)

_beginThreadex创建多线程解读 一.需要的头文件支持 #include <process.h>         // for _beginthread() 需要的设置:ProjectàSetting-->C/C++-->User run-time library 选择Debug Multithreaded 或者Multithreaded.即使用: MT或MTD. 源码如下: #include <stdio.h> #include <string>

【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇三:批量处理后的txt文件入库处理

篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblogs.com/baiboy/p/wpf1.html 篇三:批量处理后的txt文件入库处理:http://www.cnblogs.com/baiboy/p/wpf2.html 篇四:关于OneNote入库处理以及审核:http://www.cnblogs.com/baiboy/p/wpf3.html [

使用增强for循环遍历集合的时候操作集合的问题?

1 // 遍历一个list 2 public static void printList(List<String> list){ 3 for (String string : list) { 4 list.add("eeee"); // 运行错误 5 System.out.println(string); 6 } 7 System.out.println("遍历中: "+list); 8 } 9 异常信息如下: 10 Exception in threa