多线程的使用和案例

1、什么是进程?什么是线程?
进程是:一个应用程序(1个进程是一个软件)。

线程是:一个进程中的执行场景/执行单元。

注意:一个进程可以启动多个线程。
eg:对于java程序来说,当在DOS命令窗口中输入:
java HelloWorld 回车之后。会先启动JVM,而JVM就是一个进程。

JVM再启动一个主线程调用main方法(main方法就是主线程)。
同时再启动一个垃圾回收线程负责看护,回收垃圾。

最起码,现在的java程序中至少有两个线程并发,一个是 垃圾回收线程,一个是 执行main方法的主线程。

2、进程和线程是什么关系?
进程:可以看做是现实生活当中的公司。

线程:可以看做是公司当中的某个员工。

注意:
进程A和进程B的 内存独立不共享
eg:魔兽游戏是一个进程
酷狗音乐是一个进程
这两个进程是独立的,不共享资源。

3.对于单核的CPU来说,真的可以做到真正的多线程并发吗?
对于多核的CPU电脑来说,真正的多线程并发是没问题的。4核CPU表示同一个时间点上,可以真正的有4个进程并发执行。

单核的CPU表示只有一个大脑:
不能够做到真正的多线程并发,但是可以做到给人一种“多线程并发”的感觉。

对于单核的CPU来说,在某一个时间点上实际上只能处理一件事情,但是由于CPU的处理速度极快,多个线程之间频繁切换执行,给别人的感觉是:多个事情同时在做!!!

4、什么是真正的多线程并发?

t1线程执行t1的。
t2线程执行t2的。
t1不会影响t2,t2也不会影响t1。这叫做真正的多线程并发。

线程构造方法

第一种方式:

编写一个类,继承 Thread重写 run方法

  1. 怎么创建线程对象? new继承线程的类。
  2. 怎么启动线程呢? 调用线程对象的 start() 方法。
// 定义线程类
public class MyThread extends Thread{
	public void run(){
	
	}
}
// 创建线程对象
MyThread t = new MyThread();
// 启动线程。
t.start();
public class ThreadTest02 {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        // 启动线程
        //t.run(); // 不会启动线程,不会分配新的分支栈。(这种方式就是单线程。)
        t.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("分支线程--->" + i);
        }
    }
}

注意:

t.run() 不会启动线程,只是普通的调用方法而已。不会分配新的分支栈

t.start() 方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束了。
这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来,start()方法就结束了。线程就启动成功了。
启动成功的线程会自动调用run方法,并且run方法在分支栈的栈底部(压栈)。
run方法在分支栈的栈底部,main方法在主栈的栈底部。run和main是平级的。

卖票案例:

package com.example;
 
import sun.security.krb5.internal.Ticket;
 
public class MyThreadTickerSell {
    public static void main(String [] args){
    new TicketWindow().start(); //创建一个线程对象TicketWindow并开启
        new TicketWindow().start(); //创建一个线程对象TicketWindow并开启
        new TicketWindow().start(); //创建一个线程对象TicketWindow并开启
        new TicketWindow().start(); //创建一个线程对象TicketWindow并开启
    }
}
 
 
class TicketWindow extends Thread{
    private int ticket = 100;
    public void run() {
        while (true){
 
            if(ticket>0){
                Thread th = Thread.currentThread(); //获取当前线程
                String th_name = th.getName();//获取当前的线程的名字
                System.out.println(th_name+"正在发售第:"+ticket--+"张票");
            }
        }
    }
 
}

第二种方式:

编写一个类,实现 java.lang.Runnable 接口,实现run方法

  1. 怎么创建线程对象? new线程类传入可运行的类/接口。
  2. 怎么启动线程呢? 调用线程对象的 start() 方法。
// 定义一个可运行的类
public class MyRunnable implements Runnable {
	public void run(){
	
	}
}
// 创建线程对象
Thread t = new Thread(new MyRunnable());
// 启动线程
t.start();
public class ThreadTest03 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable()); 
        // 启动线程
        t.start();
        
        for(int i = 0; i < 100; i++){
            System.out.println("主线程--->" + i);
        }
    }
}

// 这并不是一个线程类,是一个可运行的类。它还不是一个线程。
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for(int i = 0; i < 100; i++){
            System.out.println("分支线程--->" + i);
        }
    }
}

注意:
第二种方式实现接口比较常用,因为一个类实现了接口,它还可以去继承其它的类,更灵活。

案例:

package com.example;
 
public class MyRunnableTest {
    public static void main (String [] args){
     TicketWindow tw = new TicketWindow();//创建TicketWindow实例化对象
        new Thread(tw,"窗口1").start();//创建线程对象并且命名窗口1,开启线程
        new Thread(tw,"窗口2").start();//创建线程对象并且命名窗口2,开启线程
        new Thread(tw,"窗口3").start();//创建线程对象并且命名窗口3,开启线程
        new Thread(tw,"窗口4").start();//创建线程对象并且命名窗口4,开启线程
    }
}
 
class TicketWindow implements  Runnable{
    private int ticket=100;
    public void run(){
        while (true){
            if(ticket>0){
                Thread th = Thread.currentThread();//获取当前线程
                String th_name = th.getName();//获取当前线程的名字
                System.out.println(th_name+"正在发售第:"+ticket--+"张票");
            }
        }
 
    }
 
}

5.线程的sleep方法

(1) 静态方法:Thread.sleep(1000);
(2)参数是毫秒
(3)作用: 让当前线程进入休眠,进入“阻塞状态”,放弃占有CPU时间片,让给其它线程使用。
                     这行代码出现在A线程中,A线程就会进入休眠。
                     这行代码出现在B线程中,B线程就会进入休眠。
(4)Thread.sleep()方法,可以做到这种效果:
         间隔特定的时间,去执行一段特定的代码,每隔多久执行一次。
 

public class ThreadTest06 {
    public static void main(String[] args) {
    	//每打印一个数字睡1s
        for(int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);

            // 睡眠1秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/WJY898989/article/details/128365498