W
e
l
c
o
m
e
: )

进程与线程

进程与线程

进程内存独立不共享
线程堆内存共享,栈独立,一个线程一个栈

分析一个问题,单核电脑能不能实行多线程并发?

多核肯定没问题
例:4核CPU表示同一时间点上,可以实现四个进程并发执行
单核不能真正的实现多线程并发:
但是Cpu的处理速度很快,多个线程之间频繁切换,给人一种多线程的感觉

创建多线程的方式

1:继承java.lang.Thread,重写run方法

package AboutThread;

public class AboutThread {
    public static void main(String[] args) {
        myThread myThread = new myThread();
        myThread.start();
//        start()方法的作用是在内存中开辟一个新的栈空间,完成之后瞬间结束,这行代码只是为了开辟一个栈空间
//        启动成功的线程会自动调用run方法,run方法在分支栈的栈底部,run和main方法是同级的
//        myThread.run();此方法不会开辟栈空间,不会并发执行

        for (int i = 0; i < 100; i++) {
            System.out.println("主线程");
//            通过输出发现,有的有的有先有后,有多有少
            
        }
    }
}

class myThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("分支线程");
        }
    }
}

2:编写一个类,实现java.lang.Runnable接口

package AboutThread;

public class ThreadTest02 {
    public static void main(String[] args) {
//        创建一个可运行的对象
        MyThread02 myThread02=new MyThread02();
//        将可运行的对象封装成一个线程对象
        Thread thread=new Thread(new MyThread02());
        thread.start();
    }
}

/*这不是一个线程类*/
class MyThread02 implements Runnable{

    @Override
    public void run() {

    }
}

注意

第二种方法最常用,因为一个类实现了一个接口还可以继承别的类,更灵活

线程生命周期

1:新建状态
start()->就绪状态
就绪状态的线程又叫做可运行状态,表示当前线程具有抢夺CPU时间片的权力(CPU时间片就是执行权)
当一个线程抢夺到CPU时间片之后,就开始执行run方法
run方法开始执行标志着线程进入运行状态
2:运行状态
当之前占有的CPU时间片用完之后,会重新回到就绪状态继续抢夺CPU时间片,
当再次抢到之后会重新进入run方法接着上一次的代码继续运行

run方法结束之后->死亡状态
线程在就绪状态与运行状态频繁切换

运行状态--->遇到阻塞事件--->阻塞状态
3:阻塞状态
当一个线程遇到阻塞状态,例如获取用户输入,此时线程会进入阻塞状态,
阻塞状态的线程会放弃之前占有的CPU时间片
阻塞解除之后会进入就绪状态继续抢夺CPU时间片

线程对象生命周期:
新建状态
就绪状态
运行状态
阻塞状态
死亡状态

获取和修改线程名

修改线程的名字:setName(),getName()
当线程没有设置名字时:
默认的名字是:Thread-0,Thread-1

获取当前线程对象
static Thread currentThread()

package Thread;


public class AboutThread {
    public static void main(String[] args) {
        Thread t1 = Thread.currentThread();
//        t1就是当前线程对象
//        这行代码在main方法中,所以当前线程就是主线程
        System.out.println(t1.getName());
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        Thread t2 = Thread.currentThread();
        super.getName();
        System.out.println(t2.getName());
    }
}

sleep()

源码: public static native void sleep(long millis) throws InterruptedException;
静态方法sleep是使当前线程进入阻塞状态,跟对象无关

package AboutThread;

public class ThreadTest02 {
    public static void main(String[] args) {
//        创建一个可运行的对象
//        将可运行的对象封装成一个线程对象
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("123");
            }
        });
        thread.start();
        try {
            thread.sleep(1000);
            
//      
//      
//            这里的sleep方法是使主线程进入阻塞状态
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

睡眠sleep()

package AboutThread;

public class SleepTest {
    public static void main(String[] args) {
        MyRunnable myRunnable=new MyRunnable();
        Thread t=new Thread(myRunnable);
        t.setName("t1");
        t.start();
        try {
            Thread.sleep(5*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
//        干扰,中断线程的睡眠
//        这种中断异常的方式依靠了Java的异常处理机制,让线程的睡眠抛出异常,之后输出异常,结束睡眠
    }
}
class MyRunnable implements Runnable{
    @Override
//    run()方法无法throws,因为父类没有抛出异常,子类不能比父类抛出更多异常
    public void run() {
        System.out.println(Thread.currentThread().getName()+"正在运行");
        try {
            Thread.sleep(1000*60*10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"结束");
    }
}

合理的终止线程

package AboutThread;

/*
stop()
stop会直接终止进程,容易丢失数据,已过时
*/
public class StopThread {
    public static void main(String[] args) {
        MyRunnable2 runnable2 = new MyRunnable2();
        Thread t1 = new Thread(runnable2);
        t1.start();
        try {
            t1.sleep(1000 * 5);
//主线程模拟睡眠5秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//5秒之后执行此语句,终端线程01
        runnable2.run = false;
    }
}

class MyRunnable2 implements Runnable {
    boolean run = true;

    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            if (run) {
                System.out.println(Thread.currentThread().getName() + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else
//            可以添加结束线程之前的代码
                return;
//        结束线程
        }


    }
}
posted @ 2021-03-10 18:28  rmxob  阅读(71)  评论(0)    收藏  举报