0基础学java之Day27(线程)

发布于:2024-12-18 ⋅ 阅读:(208) ⋅ 点赞:(0)

线程与多线程

什么是进程

进程是系统进行资源分配和调用的独立单元,每一个进程都有它的独立内存空间和系统资源。

什么是线程,理解线程和进程的关系

什么是线程?

线程是进程里面的一条执行路径,每个线程同享进程里面的内存空间和系统资源

一个进程 可以有 多个线程:各个线程都有不同的分工

理解线程和进程的关系

进程 与 进程 之间的关系:进程之间的内存空间和系统资源是独立的

同一个进程里的多条线程 :线程之间的内存空间和系统资源是共享的

进程里:可以有一条或一条以上的线程

进程里只有一条线程的情况下,这条线程就叫做主线程

进程里有多条线程的情况下,只有一条线程叫做主线程

Ps:线程是在进程里的,他们是包含关系

创建线程:

1.继承Thread类

编写步骤:写一个类继承Thread,重写父类的run()方法,在测试类的main方法中创建线程类对象,启动线程调用线程对象的start()方法

public class MyThread extends Thread{
​
    //线程对象抢到CPU资源时,才会调用run方法
    @Override
    public void run() {
        System.out.println("调用线程类的run方法");
    }
​
public static void main(String[] args) {
        
        //创建线程对象
        MyThread t = new MyThread();
        //启动线程
        t.start();
    }
    
2.实现Runnable接口

编写步骤:写一个类实现Runnable接口,重写接口的run方法,在测试类的main方法中创建接口的实现对象,创建一个Thread类的对象:Thread t = new Thread(接口的实现对象),调用start()方法启动线程

public class Task implements Runnable{
​
    @Override
    public void run() {
        System.out.println("任务类的run方法");
    }
​
    
public static void main(String[] args) {
        
        //创建任务对象
        Task task = new Task();
        //创建线程对象
        Thread t = new Thread(task);
        //启动线程
        t.start();
    }

多线程之间互相争抢资源的场景

需求:编写一个多线程的应用程序,

  • 主线程打印1-100之间的数字,

  • 子线程打印200-300之间的数字,

  • 观察其输出的结果,体会多线程互相争抢资源的场景

public class MyThread extends Thread{
​
    @Override
    public void run() {
        for (int i = 200; i <= 300; i++) {
            System.out.println("子线程:" + i);
        }
    }
​
    
public static void main(String[] args) {
        //子线程
        MyThread t = new MyThread();
        t.start();
        //主线程
        for (int i = 1; i <= 100; i++) {
            System.out.println("主线程:" + i);
        }
    }    

线程的优先级别

public final void setPriority(int newPriority) :改变线程的优先级

  • 每个线程都有一定的优先级,优先级高的线程将获得较多的执行机会。每个线程默认的优先级都与创建它的父线程具有相同的优先级。Thread类提供了setPriority(int newPriority)和getPriority()方法类设置和获取线程的优先级,其中setPriority方法需要一个整数,并且范围在[1,10]之间,通常推荐设置Thread类的三个优先级常量:

  • MAX_PRIORITY(10):最高优先级

  • MIN _PRIORITY (1):最低优先级

  • NORM_PRIORITY (5):普通优先级,默认情况下main线程具有普通优先级。

线程取名字

public class MyThread extends Thread{
    
    private String threadName;
    
    public MyThread(String threadName) {
        this.threadName = threadName;
    }
​
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(threadName + ":" + i);
        }
    }
//Thread.currentThread() -- 获取当前线程的名字    
/*
public class MyThread extends Thread{
    
    public MyThread(String name) {
        super(name);
    }
​
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            //System.out.println(super.getName() + ":" + i);
            //Thread.currentThread() -- 获取当前线程的名字
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
*/
    
public static void main(String[] args) {
        
        MyThread a = new MyThread("A");
        MyThread b = new MyThread("B");
        MyThread c = new MyThread("C");
​
        //设置优先级别
        a.setPriority(Thread.MAX_PRIORITY);
        b.setPriority(Thread.NORM_PRIORITY);
        c.setPriority(Thread.MIN_PRIORITY);
        
        a.start();
        b.start();
        c.start();
    }    

线程的休眠

使当前正public ==static== void sleep(long millis) :在执行的线程以指定的毫秒数暂停(暂时停止执行)。

 * 需求:编写点名器,倒数3秒后输出姓名
public static void main(String[] args) throws InterruptedException {
        
        Random random = new Random();
        
        String[] names = {"小红","小黄","小绿","小蓝"};
        int index = random.nextInt(names.length);
        
        for (int i = 3; i>=1; i--) {
            System.out.println(i);
            //静态方法,会让当前线程休眠
            Thread.sleep(1000);
        }
        System.out.println(names[index]);
    }

线程的礼让

public ==static== void yield():yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,希望优先级与当前线程相同或更高的其他线程能够获得执行机会,但是这个不能保证,完全有可能的情况是,当某个线程调用了yield方法暂停之后,线程调度器又将其调度出来重新执行。

线程的合并

void join() :等待该线程终止。

需求:主线程和子线程各打印200次,从1开始每次增加1,

  • 当主线程打印到10之后,让子线程先打印完再打印主线程

public class MyThread extends Thread{
​
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println("子线程:" + i);
        }
    }
    
    
public static void main(String[] args) throws InterruptedException {
        
        MyThread t = new MyThread();
        t.start();
        
        for (int i = 1; i <= 200; i++) {
            System.out.println("主线程:" + i);
            if(i == 10){
                //让子线程加入到主线程中
                t.join();
            }
        }
    }

线程的中断

public final void stop():强迫线程停止执行。 该方法具有固有的不安全性,已经标记为@Deprecated==(已过时、已废弃)==不建议再使用,那么我们就需要通过其他方式来停止线程了,其中一种方式是使用变量的值的变化来控制线程是否结束。

public void interrupt():中断线程。要通过这个方法制造InterrupttedException异常的话,前提是这个线程正在执行可能发生该异常的方法,例如:sleep,wait等。

public class MyThread extends Thread{
    
    @Override
    public void run() {
        
        //Thread.currentThread().isInterrupted() - 判断当前线程是否消亡:false表示未消亡,true表示消亡
        while(!Thread.currentThread().isInterrupted()){
            
            System.out.println("aaa");
            System.out.println("bbb");
            System.out.println("ccc");
            System.out.println("ddd");
        }
    }
​
    
 * 注意:线程的run方法执行完毕,线程就消亡了
     */
    public static void main(String[] args) throws InterruptedException {
        
        MyThread t = new MyThread();
        t.start();
        Thread.sleep(3000);
        //改变线程状态:从未消亡状态改成消亡状态 false->true
        t.interrupt();
    }
    
public class MyThread extends Thread{
    
    private boolean bool = true;
​
    public void setBool(boolean bool) {
        this.bool = bool;
    }
​
    @Override
    public void run() {
        while(bool){
            System.out.println("aaa");
            System.out.println("bbb");
            System.out.println("ccc");
            System.out.println("ddd");
        }
    }
​
    
public static void main(String[] args) throws InterruptedException {
        
        MyThread t = new MyThread();
        t.start();
        
        Thread.sleep(3000);
        //中断线程
        t.setBool(false);
    }

守护线程

public void setDaemon(true):将指定线程设置为守护线程。必须在线程启动之前设置,否则会报IllegalThreadStateException异常。

public class TestThreadMethod10 {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("我爱你");
                }
            }
        };
       // t.setDaemon(true);//把t线程变为守护线程
        //如果没有把t线程变为守护线程,那么main线程自己的任务完成之后,依然会等待你,直到你执行完毕。因为这里是死循环,等价于main方法永远不会退出
        t.start();
​
       for(int i=1; i<=10; i++){
           System.out.println("atguigu");
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
​
    }
}
public class TestThreadMethod11 {
    @Test
    public void test1(){
        Thread t = new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("我爱你");
                }
            }
        };
        t.start();
​
        //在test方法里面启动的线程,默认是守护线程
​
        for(int i=1; i<=10; i++){
            System.out.println("atguigu");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
​


网站公告

今日签到

点亮在社区的每一天
去签到