Java笔记(23):多线程(01)

Posted 花醉红尘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java笔记(23):多线程(01)相关的知识,希望对你有一定的参考价值。

1、多进程及多线程的意义:
多进程:
单进程的计算机只能做一件事情,而我们现在的计算机都可以做多件事情。
举例:一边玩游戏(游戏进程),一边听音乐(音乐进程)。
也就是说现在的计算机都是支持多进程的,可以在一个时间段内执行多个任务。
并且呢,可以提高CPU的使用率。
多线程:
多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。
程序的执行其实都是在抢CPU的资源,CPU的执行权。
多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢到CPU的执行权。
我们是不敢保证哪一个线程能够在哪个时刻抢到,所以线程的执行有随机性。

2、Java程序运行原理和JVM的启动

 1 package cn.itcast_01;
 2 /*
 3  *    进程:
 4  *        正在运行的程序,是系统进行资源分配和调用的独立单位。
 5  *        每一个进程都有它自己的内存空间和系统资源。
 6  *    线程:
 7  *        是进程中的单个顺序控制流,是一条执行路径
 8  *        一个进程如果只有一条执行路径,则称为单线程程序。
 9  *        一个进程如果有多条执行路径,则称为多线程程序。
10  *
11  *  举例:
12  *      扫雷程序,迅雷下载
13  *  
14  *  大家注意两个词汇的区别:并行和并发。
15  *        前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。
16  *        后者是物理上同时发生,指在某一个时间点同时运行多个程序。
17  *
18  * Java程序的运行原理:
19  *         由java命令启动JVM,JVM启动就相当于启动了一个进程。
20  *         接着有该进程创建了一个主线程去调用main方法。
21  * 
22  * 思考题:
23  *         jvm虚拟机的启动是单线程的还是多线程的?
24  *             多线程的。
25  *             原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。
26  *             现在的垃圾回收线程加上前面的主线程,最少启动了两个线程,所以,jvm的启动其实是多线程的。
27  */
28 public class MyThreadDemo {
29     public static void main(String[] args) {
30         System.out.println("hello");
31         new Object();
32         new Object();
33         new Object();
34         new Object();
35         //...
36         System.out.println("world");
37     }
38 }

3、实现多线程的方式和思路1

 1 package cn.itcast_02;
 2 
 3 /*
 4  * 需求:我们要实现多线程的程序。
 5  * 如何实现呢?
 6  *         由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来。
 7  *         而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程。
 8  *         Java是不能直接调用系统功能的,所以,我们没有办法直接实现多线程程序。
 9  *         但是呢?Java可以去调用C/C++写好的程序来实现多线程程序。
10  *         由C/C++去调用系统功能创建进程,然后由Java去调用这样的东西,
11  *         然后提供一些类供我们使用。我们就可以实现多线程程序了。
12  * 那么Java提供的类是什么呢?
13  *         Thread
14  *         通过查看API,我们知道了有2中方式实现多线程程序。
15  * 
16  * 方式1:继承Thread类。
17  * 步骤
18  *         A:自定义类MyThread继承Thread类。
19  *         B:MyThread类里面重写run()?
20  *             为什么是run()方法呢?
21  *         C:创建对象
22  *         D:启动线程
23  */
24 public class MyThreadDemo {
25     public static void main(String[] args) {
26         // 创建线程对象
27         // MyThread my = new MyThread();
28         // // 启动线程
29         // my.run();
30         // my.run();
31         // 调用run()方法为什么是单线程的呢?
32         // 因为run()方法直接调用其实就相当于普通的方法调用,所以你看到的是单线程的效果
33         // 要想看到多线程的效果,就必须说说另一个方法:start()
34         // 面试题:run()和start()的区别?
35         // run():仅仅是封装被线程执行的代码,直接调用是普通方法
36         // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。
37         // MyThread my = new MyThread();
38         // my.start();
39         // // IllegalThreadStateException:非法的线程状态异常
40         // // 为什么呢?因为这个相当于是my线程被调用了两次。而不是两个线程启动。
41         // my.start();
42 
43         // 创建两个线程对象
44         MyThread my1 = new MyThread();
45         MyThread my2 = new MyThread();
46 
47         my1.start();
48         my2.start();
49     }
50 }
 1 package cn.itcast_02;
 2 
 3 /*
 4  * 该类要重写run()方法,为什么呢?
 5  * 不是类中的所有代码都需要被线程执行的。
 6  * 而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码。
 7  */
 8 public class MyThread extends Thread {
 9 
10     @Override
11     public void run() {
12         // 自己写代码
13         // System.out.println("好好学习,天天向上");
14         // 一般来说,被线程执行的代码肯定是比较耗时的。所以我们用循环改进
15         for (int x = 0; x < 100; x++) {
16             System.out.println(x);
17         }
18     }
19 
20 }

4、获取和设置线程对象名称

 1 package cn.itcast_03;
 2 
 3 /*
 4  * 如何获取线程对象的名称呢?
 5  * public final String getName():获取线程的名称。
 6  * 如何设置线程对象的名称呢?
 7  * public final void setName(String name):设置线程的名称
 8  * 
 9  * 针对不是Thread类的子类中如何获取线程对象名称呢?
10  * public static Thread currentThread():返回当前正在执行的线程对象
11  * Thread.currentThread().getName()
12  */
13 public class MyThreadDemo {
14     public static void main(String[] args) {
15         // 创建线程对象
16         //无参构造+setXxx()
17         // MyThread my1 = new MyThread();
18         // MyThread my2 = new MyThread();
19         // //调用方法设置名称
20         // my1.setName("林青霞");
21         // my2.setName("刘意");
22         // my1.start();
23         // my2.start();
24         
25         //带参构造方法给线程起名字
26         // MyThread my1 = new MyThread("林青霞");
27         // MyThread my2 = new MyThread("刘意");
28         // my1.start();
29         // my2.start();
30         
31         //我要获取main方法所在的线程对象的名称,该怎么办呢?
32         //遇到这种情况,Thread类提供了一个很好玩的方法:
33         //public static Thread currentThread():返回当前正在执行的线程对象
34         System.out.println(Thread.currentThread().getName());
35     }
36 }
37 
38 /*
39 名称为什么是:Thread-? 编号
40 
41 class Thread {
42     private char name[];
43 
44     public Thread() {
45         init(null, null, "Thread-" + nextThreadNum(), 0);
46     }
47     
48     private void init(ThreadGroup g, Runnable target, String name,
49                       long stackSize) {
50         init(g, target, name, stackSize, null);
51     }
52     
53      private void init(ThreadGroup g, Runnable target, String name,
54                       long stackSize, AccessControlContext acc) {
55         //大部分代码被省略了
56         this.name = name.toCharArray();
57     }
58     
59     public final void setName(String name) {
60         this.name = name.toCharArray();
61     }
62     
63     
64     private static int threadInitNumber; //0,1,2
65     private static synchronized int nextThreadNum() {
66         return threadInitNumber++; //return 0,1
67     }
68     
69     public final String getName() {
70         return String.valueOf(name);
71     }
72 }
73 
74 class MyThread extends Thread {
75     public MyThread() {
76         super();
77     }
78 }
79 
80 */
 1 package cn.itcast_03;
 2 
 3 public class MyThread extends Thread {
 4 
 5     public MyThread() {
 6     }
 7     
 8     public MyThread(String name){
 9         super(name);
10     }
11 
12     @Override
13     public void run() {
14         for (int x = 0; x < 100; x++) {
15             System.out.println(getName() + ":" + x);
16         }
17     }
18 }

5、线程调度及获取和设置线程优先级

 1 package cn.itcast_04;
 2 
 3 public class ThreadPriority extends Thread {
 4     @Override
 5     public void run() {
 6         for (int x = 0; x < 100; x++) {
 7             System.out.println(getName() + ":" + x);
 8         }
 9     }
10 }
 1 package cn.itcast_04;
 2 
 3 /*
 4  * 我们的线程没有设置优先级,肯定有默认优先级。
 5  * 那么,默认优先级是多少呢?
 6  * 如何获取线程对象的优先级?
 7  *         public final int getPriority():返回线程对象的优先级
 8  * 如何设置线程对象的优先级呢?
 9  *         public final void setPriority(int newPriority):更改线程的优先级。 
10  * 
11  * 注意:
12  *         线程默认优先级是5。
13  *         线程优先级的范围是:1-10。
14  *         线程优先级高仅仅表示线程获取的 CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到比较好的效果。
15  *         
16  * IllegalArgumentException:非法参数异常。
17  * 抛出的异常表明向方法传递了一个不合法或不正确的参数。 
18  * 
19  */
20 public class ThreadPriorityDemo {
21     public static void main(String[] args) {
22         ThreadPriority tp1 = new ThreadPriority();
23         ThreadPriority tp2 = new ThreadPriority();
24         ThreadPriority tp3 = new ThreadPriority();
25 
26         tp1.setName("东方不败");
27         tp2.setName("岳不群");
28         tp3.setName("林平之");
29 
30         // 获取默认优先级
31         // System.out.println(tp1.getPriority());
32         // System.out.println(tp2.getPriority());
33         // System.out.println(tp3.getPriority());
34 
35         // 设置线程优先级
36         // tp1.setPriority(100000);
37         
38         //设置正确的线程优先级
39         tp1.setPriority(10);
40         tp2.setPriority(1);
41 
42         tp1.start();
43         tp2.start();
44         tp3.start();
45     }
46 }

6、线程控制之休眠线程

 1 package cn.itcast_04;
 2 
 3 import java.util.Date;
 4 
 5 public class ThreadSleep extends Thread {
 6     @Override
 7     public void run() {
 8         for (int x = 0; x < 100; x++) {
 9             System.out.println(getName() + ":" + x + ",日期:" + new Date());
10             // 睡眠
11             // 困了,我稍微休息1秒钟
12             try {
13                 Thread.sleep(1000);
14             } catch (InterruptedException e) {
15                 e.printStackTrace();
16             }
17         }
18     }
19 }
 1 package cn.itcast_04;
 2 
 3 /*
 4  * 线程休眠
 5  *        public static void sleep(long millis)
 6  */
 7 public class ThreadSleepDemo {
 8     public static void main(String[] args) {
 9         ThreadSleep ts1 = new ThreadSleep();
10         ThreadSleep ts2 = new ThreadSleep();
11         ThreadSleep ts3 = new ThreadSleep();
12 
13         ts1.setName("林青霞");
14         ts2.setName("林志玲");
15         ts3.setName("林志颖");
16 
17         ts1.start();
18         ts2.start();
19         ts3.start();
20     }
21 }

7、线程控制之加入线程

 1 package cn.itcast_04;
 2 
 3 public class ThreadJoin extends Thread {
 4     @Override
 5     public void run() {
 6         for (int x = 0; x < 100; x++) {
 7             System.out.println(getName() + ":" + x);
 8         }
 9     }
10 }
 1 package cn.itcast_04;
 2 
 3 /*
 4  * public final void join():等待该线程终止。 
 5  */
 6 public class ThreadJoinDemo {
 7     public static void main(String[] args) {
 8         ThreadJoin tj1 = new ThreadJoin();
 9         ThreadJoin tj2 = new ThreadJoin();
10         ThreadJoin tj3 = new ThreadJoin();
11 
12         tj1.setName("李渊");
13         tj2.setName("李世民");
14         tj3.setName("李元霸");
15 
16         tj1.start();
17         try {
18             tj1.join();
19         } catch (InterruptedException e) {
20             e.printStackTrace();
21         }
22         
23         tj2.start();
24         tj3.start();
25     }
26 }

8、线程控制之礼让线程

 1 package cn.itcast_04;
 2 
 3 public class ThreadYield extends Thread {
 4     @Override
 5     public void run() {
 6         for (int x = 0; x < 100; x++) {
 7             System.out.println(getName() + ":" + x);
 8             Thread.yield();
 9         }
10     }
11 }
 1 package cn.itcast_04;
 2 
 3 /*
 4  * public static void yield():暂停当前正在执行的线程对象,并执行其他线程。 
 5  * 让多个线程的执行更和谐,但是不能靠它保证一人一次。
 6  */
 7 public class ThreadYieldDemo {
 8     public static void main(String[] args) {
 9         ThreadYield ty1 = new ThreadYield();
10         ThreadYield ty2 = new ThreadYield();
11 
12         ty1.setName("LZ");
13         ty2.setName("HY");
14 
15         ty1.start();
16         ty2.start();
17     }
18 }

9、线程控制之守护线程

 1 package cn.itcast_04;
 2 
 3 public class ThreadDaemon extends Thread {
 4     @Override
 5     public void run() {
 6         for (int x = 0; x < 100; x++) {
 7             System.out.println(getName() + ":" + x);
 8         }
 9     }
10 }
 1 package cn.itcast_04;
 2 
 3 /*
 4  * public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。
 5  * 当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。 
 6  * 
 7  * 游戏:坦克大战。
 8  */
 9 public class ThreadDaemonDemo {
10     public static void main(String[] args) {
11         ThreadDaemon td1 = new ThreadDaemon();
12         ThreadDaemon td2 = new ThreadDaemon();
13 
14         td1.setName("关羽");
15         td2.setName("张飞");
16 
17         // 设置收获线程
18         td1.setDaemon(true);
19         td2.setDaemon(true);
20 
21         td1.start();
22         td2.start();
23 
24         Thread.currentThread().setName("刘备");
25         for (int x = 0; x < 5; x++) {
26             System.out.println(Thread.currentThread().getName() + ":" + x);
27         }
28     }
29 }

10、线程控制之中断线程

 1 package cn.itcast_04;
 2 
 3 import java.util.Date;
 4 
 5 public class ThreadStop extends Thread {
 6     @Override
 7     public void run() {
 8         System.out.println("开始执行:" + new Date());
 9 
10         // 我要休息10秒钟,亲,不要打扰我哦
11         try {
12             Thread.sleep(10000);
13         } catch (InterruptedException e) {
14             // e.printStackTrace();
15             System.out.println("线程被终止了");
16         }
17 
18         System.out.println("结束执行:" + new Date());
19     }
20 }
 1 package cn.itcast_04;
 2 
 3 /*
 4  * public final void stop():让线程停止,过时了,但是还可以使用。
 5  * public void interrupt():中断线程。 把线程的状态终止,并抛出一个InterruptedException。
 6  */
 7 public class ThreadStopDemo {
 8     public static void main(String[] args) {
 9         ThreadStop ts = new ThreadStop();
10         ts.start();
11 
12         // 你超过三秒不醒过来,我就干死你
13         try {
14             Thread.sleep(3000);
15             // ts.stop();
16             ts.interrupt();
17         } catch毕向东Java视频学习笔记Day11-Day13 多线程

sleep()与wait()的差别(java笔记-多线程)

java多线程笔记--synchronized类,对象,方法,代码块

Java多线程学习笔记

Java笔记(07):常见对象--StringBuffer二分查找及排序算法

Java学习笔记—多线程(java.util.concurrent.locks包,转载)