欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程概述

程序员文章站 2022-05-05 22:03:54
...

在Java中,Thread类自身不执行任何操作,它只是驱动赋予它的任务——《Java编程思想》

前言

相信很多初学Java多线程的朋友,在学了各种Runnable、Thread、wait()/notifyAll()之后,虽然能看懂已经写过的多线程代码,但是当自己要用的时候却无从下手,不清楚到底是对象还是什么其他的东西该实现Runnable,线程间的协作机制也不知道怎么加。本文将顺着《Java编程的思想》的思路,尝试概括出入门级别的使用多线程的思想。

多线程概述——多线程本质是什么?

线程有什么用?是一个实体吗?本质是什么?

例子

先从一个小程序出发:以下程序将搜索src目录下的所有java源代码文件,给定需要匹配的字段,当该java源文件中包含该字段时,输出该文件的路径。

Java多线程概述
代码的流程图如上所示,可以看到单线程的情况下,遍历文件夹判断文件是否包含目标子串两个任务都由主线程完成。如果单纯是检索文件还好,但如果要求做匹配的同时,又能快速得到整个目录的树形结构呢?显然在java源文件特别多的情况下,主线程就会在检查任务中疲于奔命,只有当所有java文件都检索一边才能得到最后的树形目录,这显然不是我们想要的。
就像“猴子法则”一样,这时候我们就会考虑将判断的检查任务分离出来,交给别人去干,主线程专心做检索目录的工作。
Java多线程概述

线程的本质

可以看到,上面的例子中,尽量避免直接使用“线程”这个术语,而且我们可以看到,要执行的任务与执行它的实体是不一样的,就好像检查任务我可以交给任何一个人一样。
这样看来,任务本身可以抽象成一个实体,而驱动它的又是另一个实体,而这个驱动任务执行的实体就是线程的本质,在Java中,我们使用 Runnable接口来表示一个任务实体,用Thread表示线程实体,使用时一般会将Runnable实体交给线程,让线程去驱动任务进行。
这也是为什么说 Java的Thread类自身不执行任何操作,它只是驱动赋予它的任务,稍微看过Java多线程的人都会知道另一种实现多线程的方式是继承Thread类,我在初学时也一直误认为“线程就是一个任务”。从概念上讲,我们希望穿件独立于其他任务运行的任务,因此我们应该能够定义任务,从实现的角度看,将任务从线程中分离出来是很有意义的。

线程的使用场景

怎么启动线程(比如说实现Runnable、继承Thread等等的),怎样用线程池等等的,可以查语法书,本文将会概括目前为止我遇到的会用到多线程的情景,然后将其做一个分类。

源代码

先提供本文图例中单线程的代码,多线程的在另一篇文章中会出现。

public class SearchFile {
	
	/**
	 * 
	 * @param file 查找的目录
	 * @param pattern 目标字符串
	 */
	public static void search(File file, String pattern) {
		if (file.isFile()) {
			if (file.getName().endsWith(".java")) {
				String fileContent = readFileContent(file);	// 读取文件的内容
				if (fileContent.contains(pattern)) {
					System.out.format("在 %s 中匹配到了 %s %n", file.getAbsolutePath(), pattern);
				}
			}
		}
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (File f : files) {
				search(f, pattern);
			}
		}
	}
	
	public static String readFileContent(File file) {
		FileReader fileReader = null;
		try {
			fileReader = new FileReader(file);
			char[] chars = new char[(int)file.length()];
			fileReader.read(chars);
			return new String(chars);
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return null;
		} finally {
			if (fileReader != null) {
				try {
					fileReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void main(String[] args) {
		File folder = new File("src");
		System.out.println(folder.isDirectory());
		search(folder, "static");
	}
}

参考资料

  1. 《Java编程思想》
  2. How2j多线程专题