package cn.ekgc.javasenior.day20210630;
public class ThreadNote {
public static void main(String[] args) {
/*
* 1、程序、进程和线程:
* (1)程序:由代码组成,为了完成某项功能业务,或者是实现某个应用而形成的代码集合。
* 程序本身就是一个静止的概念,也就是当通过代码写完之后,就能够得到一个程序。
* (2)进程:当开始通过 CPU 去执行某个程序的代码时,那么这个程序就需要操作系统开始独立分配存储空间,
* 将其的代码交给 CPU 开始运行,那么这个时候,这个静止的程序,就成为了动态的进程。
* 程序是静止的,而进程就是运行的程序,是一个动态的。
* 对于进程来说,有如下的特征:
* A、是动态运行的;
* B、是计算机运行的独立单位;
* C、操作系统在分配内存空间时,是以进程为单位进行分配的,每个进程之间的存储空间是独立的,相互不干扰。
* 进程的缺点在于,一个独立的进程会执行很多的代码,往往所需要的时间或者是等待时间过长,
* 例如微信在聊天时,就会有大量空闲的时间在等待用户的输入,而 CPU 的执行效率较高,
* 就会造成 CPU 在大量时间下一直处于空转状态。造成 CPU 的资源浪费。
* 如果 CPU 的运行是以进程为单位执行的话,那么就会造成 CPU 在大部分时间下处于空转,
* 而且还不允许其他进程执行,造成宝贵的 CPU 资源浪费。
* (3)线程:线程是 CPU 运行的最小单位,是将一个独立的进程再次进行细化,变为多个更小的运行单位,
* 我们将这个单位就称之为线程。由于线程是 CPU 运行的最小单位,因此对于 CPU 来说,是不存在进程这一概念,
* 那么他就可以在多个线程之间进行轮流交替执行,提高 CPU 的工作效率。
* 线程存在的最重要的目的就是减少 CPU 的空转时间,提高 CPU 的利用率。
* 2、多线程指的就是一个程序在执行的时候,可以同时存在多个线程。自此之前,我们所写的所有程序,
* 本质上只有一个线程,那么就是由 main() 方法所创建的线程,我们称之为主线程。
* 每开辟一个线程,那么这个线程就脱离了主线程,能够独立运行。
* 3、线程的特征:
* (1)线程是 CPU 执行的最小单位;
* (2)一个进程内可以存在多个线程;
* (3)一个进程内的多个线程之间是共享内存的,相互之间是可以通讯交流的。
* 4、对于 Java 来说,要想实现多线程,是很简单的,因为 Java 已经将多线程的实现进行了封装,
* 我们只需要直接使用即可。
*/
}
}
Thread
package cn.ekgc.javasenior.day20210630.base;
public class ThreadDemo01 {
public static void main(String[] args) {
// 创建 MyThread 对象
MyThread myThread = new MyThread();
// 对于每个线程,都可以进行命名,则通过该线程的 setName() 进行命名
myThread.setName("李静平");
// 如果只是创建了一个线程对象,那么这个线程是不执行的,需要调用该线程对象的 start() 启动该线程
// 即使启动了一个线程,那么这个线程也不一定就立刻被执行,只有当操作系统调度该线程为其分配 CPU 资源后,
// 这个线程才能够执行。
myThread.start();
// 那么此时对于操作系统来说就存在两个线程,分别是 main 和 myThread,
// 当 myThread 启动后,这个线程就脱离了 main 的管理,独立运行,
// 也设定 main 线程运行的内容
for (int i = 0; i < 100; i++) {
System.out.println("这是 main 线程的第 " + (i + 1) + " 次输出!");
}
}
}
// 一个 .java 文件中,可以存在多个 class 类,但是只能够有一个 public class
// 虽然多个 class 可以写在一个 .java 文件中,但是编译之后获得的 .class 文件
// 确是一个 class 类一个独立的 .class 文件。
// 要想获得一个能够创建线程的类,只需要让该类继承 java.lang.Thread 类即可
class MyThread extends Thread {
// 对于一个线程来说,只运行该线程的 run(),因此需要运行的代码必须写在 run()
// 重写 run()
@Override
public void run() {
// 如果需要得到到时候的线程名,则可以通过 Thread.currentThread().getName() 获得
String threadName = Thread.currentThread().getName();
// 当创建了一个 MyThread 线程执行,会执行的代码
for (int i = 0; i < 100; i++) {
System.out.println("这是 " + threadName + " 线程的第 " + (i + 1) + " 次输出!");
}
}
}
package cn.ekgc.javasenior.day20210630.base;
public class Threadtest {
public static void main(String[] args) {
Mythread01 my = new Mythread01();
my.setName("李静平");
my.start();
for(int i = 0;i<10;i++) {
System.out.println("这是main第"+(i+1)+"次运行");
}
}
}
class Mythread01 extends Thread{
@Override
public void run() {
String threadname = Thread.currentThread().getName();
for(int i = 0;i<10;i++) {
System.out.println("这是"+threadname+"第"+(i+1)+"次运行");
}
}
}
Runnable
package cn.ekgc.javasenior.day20210630.base;
public class RunnableDemo01 {
public static void main(String[] args) {
// 创建 MyRunnable 类的对象
MyRunnable myRunnable = new MyRunnable();
// 创建 Thread 对象,并且将 MyRunnable 对象作为构造方法的参数传入
Thread myThread = new Thread(myRunnable);
// 启动 myThread 线程
myThread.start();
for (int i = 0; i < 100; i++) {
System.out.println("这是 main 的第 " + (i + 1) + " 次运行!");
}
}
}
// 要想获得一个多线程类,除了继承 Thread 类,也可以实现 Runnable 接口
class MyRunnable implements Runnable {
// 对于实现了 Runnable 接口的类对象,只是线程在启动后需要运行的部分,
// 而不是线程本身
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("这是 MyRunnable 的第 " + (i + 1) + " 次运行!");
}
}
}
package cn.ekgc.javasenior.day20210630.base;
public class Runnabletest {
public static void main(String[] args) {
Thread my01 = new Thread(new MyRunnable01());
my01.start();
for(int i = 0;i<10;i++) {
System.out.println("这是main第"+(i+1)+"次运行");
}
}
}
class MyRunnable01 implements Runnable{
@Override
public void run() {
for(int i = 0;i<10;i++) {
System.out.println("这是Runnable第"+(i+1)+"次运行");
}
}
}
package cn.ekgc.javasenior.day20210630.schedule;
public class JoinDemo {
public static void main(String[] args) {
// 创建 MyJoinThread 对象
MyJoinThread joinThread = new MyJoinThread();
// 设定当前线程名
joinThread.setName("MyJoinThread");
for (int i = 0; i < 10; i++) {
System.out.println("这是 main 线程的第 " + (i + 1) + " 次运行!");
if (i == 5) {
// 启动线程
// 启动 MyJoinThread 线程
joinThread.start();
// 该线程启动后,直接加入运行,让 main 进入到等待阻塞中
try {
joinThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class MyJoinThread extends Thread {
@Override
public void run() {
// 获得当前线程名
String name = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
System.out.println("这是 " + name + " 的第 " + (i + 1) + " 次运行!");
}
}
}
package cn.ekgc.javasenior.day20210630.schedule;
public class PriorityDemo {
public static void main(String[] args) {
// 创建 MyThread 对象
MyPriorityThread myThread = new MyPriorityThread();
// 对 myThread 线程进行命名
myThread.setName("MyThread");
/*
* 对于任意的一个线程,都存在优先级别,分别是从 1 ~ 10,默认为 5。
* 也就是每个线程都有平等的抢占 CPU 资源的能力。
* 但是如果需要某些线程更好的能够抢占到 CPU 资源,
* 那么可以通过调整该线程的优先级别,来调整该线程抢占 CPU 的能力,
* 表明该线程抢占 CPU 能力越高,抢占到 CPU 的概率越大。
* 但是不保证就一定能够抢到 CPU 资源。
*/
// 在该线程启动前,可以调整线程的优先级别
myThread.setPriority(10);
// 启动 myThread 线程
myThread.start();
for (int i = 0; i < 10; i++) {
System.out.println("这是 main 的第 " + (i + 1) + " 次运行!");
}
}
}
class MyPriorityThread extends Thread {
@Override
public void run() {
// 获得当前线程的线程名
String name = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
System.out.println("这是 " + name + " 的第 " + (i + 1) + " 次运行!");
}
}
}
package cn.ekgc.javasenior.day20210630.schedule;
public class SleepDemo {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println("这是 main 的第 " + (i + 1) + " 次运行!");
// 让 main 线程,每一轮循环都休眠 1s
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package cn.ekgc.javasenior.day20210630.schedule;
public class SortDemo {
public static void main(String[] args) {
int[] nums = {10, 2, 9, 1, 6, 5, 7};
for (int i = 0; i < nums.length; i++) {
SortThread sortThread = new SortThread(nums[i]);
sortThread.start();
}
}
}
class SortThread extends Thread {
private int num;
public SortThread(int num) {
this.num = num;
}
@Override
public void run() {
// 根据 num,让当前线程进行休眠
try {
Thread.sleep(num * 1000);
System.out.println(num);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package cn.ekgc.javasenior.day20210630.schedule;
public class YieldDemo {
public static void main(String[] args) {
// 创建 MyJoinThread 对象
YieldThread yieldThread = new YieldThread();
// 设定当前线程名
yieldThread.setName("YieldThread");
yieldThread.start();
for (int i = 0; i < 10; i++) {
System.out.println("这是 main 线程的第 " + (i + 1) + " 次运行!");
// 每次输出完,都将 main 移出 CPU
Thread.yield();
}
}
}
class YieldThread extends Thread {
@Override
public void run() {
// 获得当前线程名
String name = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
System.out.println("这是 " + name + " 的第 " + (i + 1) + " 次运行!");
}
}
}