多线程:
1、什么是进程?什么是线程?
进程是一个应用程序。(一个进程是一个软件)
线程是一个进程中的执行场景/执行单元。
一个进程可以启动多个线程。
2、对于java程序来说,当DOS命令窗口输入:
java HelloWorld回车之后。
会先启动JVM,而JVM就是一个进程。
JVM再启动一个主线程调用main方法。
同时再启动一个垃圾回收线程负责看护,回收垃圾。
最起码,现在的java程序中至少有两个线程并发,
一个是垃圾回收线程,一个是执行main方法的主线程。
3、进程和线程是什么关系?
阿里巴巴:进程
马云:阿里巴巴的一个线程
童文红:阿里巴巴的一个线程
京东:进程
强东:京东的一个线程
妹妹:京东的一个线程
进程可以看做是现实生活当中的公司。
线程可以看做是公司当中的某个员工。
注意:进程A和进程B的内存独立不共享。
在java语言中:
线程A和线程B,堆内存和方法区内存共享
但是栈内存独立,一个线程一个栈。
java中之所以有多线程机制,目的就是为了提高程序的处理效率。
4、使用了多线程机制之后,main方法结束,是不是有可能程序也不会结束。
main方法结束只是主线程结束了,主栈空了,其他栈(线程)可能还在
压栈弹栈。
5、分析一个问题:对于单核CPU来说,真的可以做到真正的多线程并发吗?
对于多核CPU的电脑来说,真正的多线程并发是没有问题的。
4核CPU表示同一个时间点上,可以真正的有四个进程并发执行。
什么是真正的多线程并发?
t1线程执行t1的
t2线程执行t2的
t1不会影响t2,t2不会影响t1,这叫做真正的多线程并发。
单核CPU表示只有一个大脑:
不能做到真正的多线程并发,但是可以做到给人一种“多线程并发”的感觉。
对于单核CPU来说,在某一个时间点上实际上只能处理一件事,但是由于CPU
的处理速度击垮啊,多个线程之间频繁切换执行,给人的感觉来说:多个事情
在同时做。
6、java语言中,实现线程有两种方式
java支持多线程机制。并且java已经将多线程实现了,我们只需要继承。
尽量采用第二种:面向接口编程,java只能单继承,一个类实现了接口,还能继承别的类。
第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法
//定义线程类
public class MyThread extends Thread{
@Override
public void run(){
}
}
//创建线程对象
MyThread myThread=new MyTread();
//启动线程
myThread.start();
第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法。
//定义一个可运行的类继承Runnable
public class MyRunnable extends Runnable{
@Override
public void run(){
}
}
//创建线程对象
Thread t=new Thread(new MyRunnable());
//启动线程
t.start();
第三种方式:FutureTask方式,实现Callable接口(JDK8新特性)
这种方式实现的线程可以获取线程的返回值。
之前讲解的那两种方式是无法获取线程返回值的,因为run方法返回void。
实现Callable接口
这种方式的优点:可以获取线程的执行结果
缺点:效率较低,在获取t线程执行结果的时候,当前线程受阻塞,效率较低。
代码演示:第一种方式
public static void main(String[] args) {
//这是main方法,这里的代码属于主线程,在主栈中运行。
//新建一个分支线程对象
MyThread myThread=new MyThread();
//启动线程
//myThread.run();//不会启动线程,不会分配新的分支栈。
//start()方法的作用是:启动一个分支线程,在JVM中开辟有一个新的栈空间,这段代码任务完成之后,瞬间就结束了。
//这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来,start()方法就结束了。线程启动成功了。
//启动成功的线程会自动调用run()方法,并且run方法在分支线程的栈底部(压栈)
//run方法在分支线程的底部,main方法在主栈的栈底部,run和main是平级的。
myThread.start();//瞬间就结束了。
//这里的代码还是运行在主线程中。
for (int i = 0; i <1000 ; i++) {
System.out.println("主线程————>"+i);
}
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println("分支线程————>