Java多线程概述

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

前言

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

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

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

例子

先从一个小程序出发:以下程序将搜索src目录下的所有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多线程专题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
抱歉,我无法通过文字回答您所提供的多线程知识点流程图。然而,我可以为您提供一个简单的文字描述来帮助您理解Java多线程的核心概念和流程: 1. 首先,创建一个线程类。这可以通过继承Thread类或实现Runnable接口来实现。 2. 在线程类中,重写run()方法。这个方法包含了线程要执行的代码逻辑。 3. 创建线程的实例。如果使用继承Thread类的方式,直接实例化线程类即可。如果使用实现Runnable接口的方式,需要创建一个Thread对象,并将实现了Runnable接口的类的实例作为参数传递给Thread的构造方法。 4. 调用start()方法启动线程。start()方法会启动一个新的线程,并在新线程中执行run()方法中的代码。 5. 当线程开始执行时,它会进入就绪状态,等待操作系统分配CPU资源。 6. 一旦获得CPU资源,线程就会进入运行状态,并开始执行run()方法中的代码。 7. 在运行过程中,线程可能会被阻塞,例如等待IO操作完成或等待其他线程的完成。当这些条件满足时,线程将重新进入就绪状态,等待再次获得CPU资源。 8. 当线程执行完run()方法中的代码后,它将进入终止状态,表示线程的生命周期已经结束。 请注意,这只是一个简单的概述,涉及到更多的细节和概念,例如线程同步、互斥、等待和通知等。如果您需要更详细的信息,请提出您想要了解的具体问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值