多线程
1.什么是进程?什么是线程?
进程是一个应用程序(一个进程是一个软件)
线程是一个进程中的执行场景/执行单元
一个进程可以启动多个线程
2.对于java程序来说,当在DOS命令窗口中输入:java Helloworld 回车之后。会先启动JVM,而JVM就是一个进程。JVM再启动一个主线程调用main方法,同时再启动一个垃圾回收线程负责看护,回收垃圾。最起码,现在的java程序中,至少有两个线程并发,一个是垃圾回收线程,一个是执行main方法的主线程。
3.进程和线程是什么关系?
进程可以看作是一个公司,线程可以看作是进程中的某个员工。
注:进程A和进程B的内存独立不共享,可以理解为两个公司的资源不能共享
线程A和线程B:只要是一个进程里的,堆内存和方法区内存共享;但是栈内存独立,一个线程一个栈。

假设启动10个线程,会有10个栈空间,每个栈和每个栈之间互不干扰,各自执行各自的,这就是多线程并发。
火车站可以看作一个进程,火车站中每一个售票窗口可以看作是一个线程,A乘客可在窗口1购票,B乘客可在窗口2购票,A不需要等B,所以多线程并发可以提高效率。
java中之所以有多线程机制,目的就是为了提高程序的处理效率。
4.使用多线程机制之后,main方法结束后,程序可能也不会结束,main方法结束只是主线程结束了,主栈空了,但是其他的栈(线程)可能还在压栈弹

5.对于单核的CPU来说,可以做到真正的多线程并发吗?(对于多核CPU来说,真正的线程并发是没问题的,4核CPU表示同一个时间点上,可以真正的有4个进程并发执行)
什么是真正的多线程并发?
t1线程执行t1的,t2线程执行t2的,两者相互不影响,这叫做真正的多线程并发。
单核CPU表示只有一个大脑,不能做到真正的多线程并发,在某个时间点上只能处理一件事情,但是由于人的反应速度比较慢,而CPU的处理速度极快,多个线程之间频繁快速切换执行,给人造成的感觉就多线程并发,即多个事情同时在做。
例如:线程A播放音乐,线程B运行游戏,单核CPU在一个时间点只能运行一个线程,但是由于A与B之间来回切换的速度极快,所以给人的感觉就是音乐一直在播放,音乐一直在运行,即它们是同时并发的。
6.线程分析
1 package XianChengFenXi; 2 3 4 //分析程序有几个线程 5 //除垃圾回收之外有几个线程 6 7 8 //因为程序只有一个栈,所以除了垃圾回收之外,只有一个线程 9 public class ThreadTest1 { 10 public static void main(String[] args){ 11 System.out.println("main begin"); 12 m1(); 13 System.out.println("main over"); 14 } 15 16 private static void m1(){ 17 System.out.println("m1 begin"); 18 m2(); 19 System.out.println("m1 over"); 20 } 21 22 private static void m2(){ 23 System.out.println("m2 begin"); 24 m3(); 25 System.out.println("m2 over"); 26 } 27 28 private static void m3(){ 29 System.out.println("m3 execute"); 30 } 31 32 }

6.java语言中。实现线程有两种方式:
java支持多线程机制,并且java已经将多线程实现了,只需要继承就行。
(1)第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法
1 package XianChengFenXi; 2 11 public class ThreadTest02 { 12 public static void main(String[] args){ 13 //这里是main方法,这里的代码属于主线程,在主栈中运行。 14 15 //创建一个分支线程对象 16 MyThread myThread=new MyThread(); 17 18 myThread.run(); //若直接调用run()方法,而不事先启动start()方法,则不会分配新的分支栈,还是在主栈中进行,为单线程。 28 for(int i=0;i<10;i++){ 29 System.out.println("主线程++++++++"+i); 30 } 31 32 } 33 34 } 35 class MyThread extends Thread{ 36 public void run(){ 37 //编写程序,这段程序运行在分支栈 38 for(int i=0;i<10;i++){ 39 System.out.println("分支线程——————————"+i); 40 } 41 42 } 43 }
运行结果:可以看到,这就是简单的主栈中的方法调用,并没有进行线程并发。

---------------------------------------------------------------------------------------------------------------------------------
1 package XianChengFenXi; 2 3 4 /* 5 * 实现线程的第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法 6 * 7 * 如何创建线程对象? new就行了 8 * 怎么启动线程? 调用线程对象的start()方法 9 */ 10 11 public class ThreadTest02 { 12 public static void main(String[] args){ 13 //这里是main方法,这里的代码属于主线程,在主栈中运行。 14 15 //创建一个分支线程对象 16 MyThread myThread=new MyThread();19 20 //启动线程 21 //start()方法的作用是,启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成后,瞬间就结束了 22 //这段代码的任务只是为了开辟一个新的栈空间,只要新的栈空间开出来,start()方法就结束了,线程就启动成功了 23 //启动成功的线程会自动调用run方法,并且run方法在分支栈的底部(压栈)。 24 //run()方法在分支栈的栈底部,main方法在主栈的栈底部,run和main是平级的 25 myT hread.start(); 26 27 //这里的代码还是运行在主线程中 28 for(int i=0;i<10;i++){ 29 System.out.println("主线程++++++++"+i); 30 } 31 32 } 33 34 } 35 class MyThread extends Thread{ 36 public void run(){ 37 //编写程序,这段程序运行在分支栈 38 for(int i=0;i<10;i++){ 39 System.out.println("分支线程——————————"+i); 40 } 41 42 } 43 }
运行结果:多线程并发

注:结果中出现主线程、分支线程交替输出,有多有少,有先有后,原因是:因为控制台只有一个,存在先执行后打印的情况。
(2)第二种方式:编写一个类,实现java.lang.Runnable接口,实现run()方法
package XianChengFenXi; /* 实现线程的第二种方式:编写一个类实现java.lang.Runnable接口 */ public class ThreadTest3 { public static void main(String[] args){ //创建一个可运行的对象 MyRunnable r=new MyRunnable(); //将可运行的对象封装成一个线程对象 Thread t=new Thread(r); //启动线程 t.start(); for(int i=0;i<10;i++){ System.out.println("主线程++++++++"+i); } } } //这并不是一个线程类,是一个可运行的类,它还不是一个线程 class MyRunnable implements Runnable { public void run(){ for(int i=0;i<10;i++){ System.out.println("分支线程——————————"+i); } } }
注意:第二种方式实现接口比较常用,因为一个类实现了接口,它还可以去继承其它的类,更灵活
-------------------------------------------------------------------------------------------------------------------------------------
(3第三种方式:采用匿名内部类
1 package XianChengFenXi; 2 3 4 //采用匿名内部类 5 public class ThreadTest4 { 6 public static void main(String[] args){ 7 //创建线程对象,采用匿名内部类方式 8 //这是通过一个没有名字的类,new出来的对象 9 Thread t=new Thread(new Runnable(){ 10 public void run(){ 11 for(int i=0;i<10;i++){ 12 System.out.println("分支线程------"+i); 13 } 14 } 15 }); 16 17 /* 18 * 与上面的代码功能一样,只是拆开了写 19 Runnable r=new Runnable(){ 20 public void run(){ 21 for(int i=0;i<10;i++){ 22 System.out.println(i); 23 } 24 } 25 }; 26 27 Thread t=new Thread(r); 28 29 30 */ 31 32 //启动线程 33 t.start(); 34 for(int i=0;i<10;i++){ 35 System.out.println("主线程+++++++"+i); 36 } 37 38 } 39 40 }

浙公网安备 33010602011771号