开篇
自学Java刚好一个月了,希望通过写博客输出一下,总结自己所学
学前须知
要想了解多线程的问题,我们首先要知道“并发”和“并行”这两个概念
并发
是指在一个时间段内多个不同的程序“同时“发生,这里的”同时“并不是真正意义上的同时,因为在这个时间段上的不同时间点所执行的程序是不同的
并行
说完并发,那么并行就可以说是真正意义上的同时了,它是指在同一个时间点上的不同程序同时发生
进程和线程
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程,有时被称为轻量进程,是程序执行流的最小单元。
以上概念可能会不好理解,其实就是说线程是进程的一个实体,是比进程更小的且能独立运行的基本单位
多线程
多线程的概念: 是指从软件或者硬件上实现多个线程并发执行的技术
现在我想大家就可以很清晰的理解这个概念了吧 1
多线程的创建
多线程的创建有三种方式:继承Thread类、实现Runnable接口、实现Callable接口,由于学习进度有限,在此只总结前两种方式2
(一)继承Thread类
我们先来看看代码
package test1;
class myThread extends Thread
{
private String name;
myThread(String name)
{
this.name = name;
}
public void run() {
for(int x = 0;x < 5;x++)
{
System.out.println(name+"..."+x);
}
}
}
public class StackTraceTest {
public static void main(String[] args) {
myThread t1 = new myThread("俺是老大");
myThread t2 = new myThread("俺是老二");
myThread t3 = new myThread("瞎说,俺才是老大");
t1.start();
t2.start();
t3.start();
}
}
再看看运行结果
这就是继承Thread类描述多线程的方式,具体分析的内容如下
程序为何调用start(),而不是run()
看了上面的代码操作,大家可能会疑惑为何程序myThread类中写的方法是run(),而在主方法中调用的是start()
为了让大家更清晰的理解run(),我们就在主方法中把调用start()改为调用run()
代码如下
package test1;
class myThread extends Thread
{
private String name;
myThread(String name)
{
this.name = name;
}
public void run() {
for(int x = 0;x < 5;x++)
{
System.out.println(name+"..."+x);
}
}
}
public class StackTraceTest {
public static void main(String[] args) {
myThread t1 = new myThread("俺是老大");
myThread t2 = new myThread("俺是老二");
myThread t3 = new myThread("瞎说,俺才是老大");
t1.run();
t2.run();
t3.run();
}
}
运行结果如下
我们可以清晰的看到代码变成了顺序执行,这说明如果我们直接调用run()方法,其方法还是运行在主线程中的,而没有再单独开辟一条线路出来
如果各位还是觉得很模糊,那我再用图形的方式来解读一下
首先看一段代码
package test1;
class myThread2 extends Thread {
public void run()
{
for(int i = 0;i < 50;i++)
{
System.out.println("run..."+i);
}
}
}
class ThreadDemo
{
public static void main(String[] args) {
myThread2 mt = new myThread2();
mt.start();
for(int x = 0;x < 50;x++)
System.out.println("主线程....."+x);
}
}
以下是代码的线程图和部分运行结果 (因为是第一次写博客,对使用Markdown的格式和方法还不是太熟,所以使用了画图工具,图形太难看了,请谅解…)
根据以上演示,可以看到start()方法的作用有两个:
1.启动线程(也就相当于开辟了一条新道路)
2.执行run()方法
所以也就解释了我们一开始的疑问 —>为什么在主方法中调用的是start()方法而不是run()方法?
聊完了继承Thread类的方式,接下来就是介绍实现Runnable接口的方式,但在此之前,有一个小小的问题就是多线程的创建有了继承Thread类的方式了,为何还要再来一个实现Runnable接口的方式呢??
(二)实现Runnable接口
对于上面的问题,其实是因为Java不像C++那样支持多继承,所以当一个类继承了非Thread类,而又想使用多线程的功能时,这时就要考虑实现Runnable接口的方式了
通过查阅API文档可知:
public static Thread currentThread()
返回对当前正在执行的线程对象的引用
public final String getName()
返回此线程的名称
public Thread(Runnable target,String name)
参数 :
target — 启动此线程时调用其run方法的对象。 如果null ,则调 用此线程的run方法
name — 新线程的名称
故写出代码:
package test1;
class myThread3 implements Runnable
{
public void run()
{
for(int i = 0;i < 3;i++)
{
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}
public class CallableTest {
public static void main(String[] args) {
myThread3 mt1 = new myThread3();
myThread3 mt2 = new myThread3();
myThread3 mt3 = new myThread3();
Thread t1 = new Thread(mt1,"俺是老大");
Thread t2 = new Thread(mt2,"俺是老二");
Thread t3 = new Thread(mt3,"瞎说,俺才是老大");
t1.start();
t2.start();
t3.start();
}
}
运行结果如下
(三)对比分析
对比这两种创建多线程的方式,显然是后者更好,因为实现接口的方式比继承类的方式更加灵活,也能减少程序之间的耦合度3
多线程的产生原因
是为了提高程序的运行效率,利用CPU的分时机制,尽可能的提高CPU的“利用率”
总结
这是本人第一次写博客,所以有任何不妥的地方还请各位海涵,希望能同大家一起进步!
参考:
- https://blog.csdn.net/hightrees/article/details/80558211
- https://blog.csdn.net/weixin_42956047/article/details/96432970
- https://www.runoob.com/java/java-multithreading.html