多线程主要作用是充分利用Cpu,而不在于它的乱序性。不讲它竞争什么的、乱序打印ABC的例子什么的,那些有意义吗?
这个Demo 是多线程打印文件夹下的文件,主要实现是用数组存放文件,一个游标遍历。
我们需要考虑在什么时候加互斥访问,本例用synchronized .
先考虑单线程的流程:客户端启动-->读取文件下的文件放到数组(IO)--> 取游标打印 ,游标加1 -- > 改文件写文件(IO) -- 重复上两步至越界 -- 结束
多线程时显然需要在“取游标打印 ,游标加1 ”这一步加互斥,扔到一个方法里面加synchronized修饰符。
代码:
Client.java
package mutilThread;
import java.io.File;
/**
* 多线程打印文件夹下的文件名
*
*/
public class Client {
private static File[] files ;//文件数组
private static int curr = 0; //文件数组的游标,增加时需考虑线程安全
public static void main(String[] args) {
File folder = new File("C:/test");
if (folder.isDirectory()) {
files = folder.listFiles();
}
Thread t = null;
for (int i = 0; i < 5; i++) {
t = new Thread(new ReadThread());
t.start();
System.out.println(t.getName() + " started.");
}
}
// getter/setter
public static int getCurr() {
return curr;
}
public static void setCurr(int curr) {
Client.curr = curr;
}
public static File[] getFiles() {
return files;
}
}
ReadThread.java
package mutilThread;
import java.io.File;
public class ReadThread implements Runnable {
private boolean flag = true; // 线程运行标志,true 线程则一直运行,false则 while 循环停止,run
// 执行完毕,线程自然结束
@Override
public void run() {
while (flag) {
File file = getFile();
if (file != null) {
System.out.println(file.toString() + " by "
+ Thread.currentThread().getName());
// 实际需求会有一些IO操作,如修改再保存之类,用计算来睡眠模拟
try
{
Thread.sleep((long)(Math.random() * 1000));
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}else stopThread();// 停止线程</span>
}
}
/**
* synchronized,此方法互斥访问
* @return 一个文件
*/
private synchronized static File getFile() {
int curr = Client.getCurr();
File[] files = Client.getFiles();
// 游标越界则停止
if (curr > files.length - 1) {
System.out.println("finished by "
+ Thread.currentThread().getName());
return null;
}
File file = files[curr];
Client.setCurr(++curr);
return file;
}
private void stopThread() {
this.flag = false;
}
}
停止线程使用while(flag) 方式,以后就这样套着写一个Thread即可
我们执行一个任务的时候,需要加速,那就多线程吧。对可能会因并发而错乱的地方加同步即可,简单实用。
关于线程数的问题,我测试10次发现线程数达到核心数后总体速度不会再增加. 最佳线程数是 核心数+1 .