Java中的线程

-------- 线程相关概念

进程 (Process):是计算机中的程序关于某数据集合上的一次运行活动,是操作系统进行资源分配与调度的基本单位。可以把进程简单地理解为正在操作系统中运行的一个程序

线程 (Thread):是进程的一个执行单元。一个线程就是进程中一个单一顺序的控制流,是进程的一个执行分支。进程是线程的容器,一个进程有至少一个或多个线程。

在操作系统中是以进程为单位分配资源,如CPU、虚拟存储空间等。多个线程共享同一个进程的资源。每个线程都有各自的线程栈,自己的寄存器环境,自己的线程本地存储。

主线程:JVM启动时会创建一个主线程,该主线程负责执行main方法。主线程就是运行main方法的线程。

Java中的线程不是孤立的,线程之间存在一些联系。如果在A线程中创建了B线程,称B线程为A线程的子线程,相应的A线程就是B线程的父线程。

串行,并发与并行:串行是指各个任务依次执行,并发是指在某段时间内交替完成多个任务;并行是同时完成多个任务。

 

并发可以提高事物的处理效率,即一段时间内可以处理或者完成更多的事情。并行是一种更为严格,理想的并发。

从硬件角度来说,如果是单核CPU,一个处理器一次只能执行一个线程的情况下,处理器可以使用时间片轮转技术,可以让CPU快速的在各个线程之间进行切换,对于用户来说,感觉是三个线程在同时执行。如果是多核心CPU,可以为不同的线程分配不同的CPU内核。

-------- 线程的创建与启动

在Java中,创建一个线程就是创建一个 Thread 类(子类)的对象(实例)。

Thread 类有两个常用的构造方法:Thread() 与 Thread(Runnable)。对应的创建线程的两种方式

  • 定义 Thread 类的子类,即继承 Thread 类。
  • 定义一个 Runnable 接口的实现类(常用)

这两种创建线程的方式没有本质的区别。因为Java中的类只允许单继承,当线程类继承了 Thread 后就不能再继承其他类了,所以开发中经常使用实现 Runnable 接口的形式创建线程,这样 Runnable 实现类还可以继承其他类,使用更灵活。

// 方式一:定义一个类继承 Thread类
public class MyThread extends Thread {
    //2) 重写Thread父类中的run(),run()方法体中的代码就是子线程要执行的任务
    @Override
    public void run() {
        System.out.println("这是子线程打印的内容");
    }
}
// 测试类
public class Test {
    public static void main(String[] args) {
        System.out.println("JVM启动main线程,main线程执行main方法");
        //3)创建子线程对象
        MyThread thread = new MyThread();
        //4)启动线程
        thread.start();
        /*
            调用线程的start()方法来启动线程, 实质就是请求JVM运行相应的线程,这个线程具体在什么时候运行由线程调度器(Scheduler)决定。注意:
                start()方法调用结束并不意味着子线程开始运行
                线程调度器选中执行线程时执行线程的run()方法
                如果开启了多个线程,start()调用的顺序并不一定就是线程启动的顺序
                多线程运行结果与代码执行顺序或调用顺序无关
         */
        System.out.println("main线程后面其他 的代码...");
    }
}
// 方式二:定义类实现Runnable接口
public class MyRunnable implements Runnable {
    //2) 重写Runnable接口中的抽象方法run(),run()方法就是子线程要执行的代码
    @Override
    public void run() {
        for(int i = 1; i < 5; i++){
            System.out.println( "子线程1:" + i);
        }
    }
}
// 测试类
public class Test {
    public static void main(String[] args) {
        //3) 创建Runnable接口的实现类对象
        MyRunnable  runnable = new MyRunnable();
        //4)创建线程对象
        Thread thread = new Thread(runnable);
        //5)开启线程
        thread.start();

        // 当前是main线程
        for(int i = 1; i<5; i++){
            System.out.println( "main==> " + i);
        }

        // 有时调用Thread(Runnable)构造方法时,实参也会传递匿名内部类对象
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 1; i<5; i++){
                    System.out.println( "子线程2:" + i);
                }
            }
        });
        thread2.start();
    }
}

-------- 线程的常用方法

  • static Thread currentThread()  返回对当前正在执行的线程对象的引用。
  • void setName(String name)  改变线程名称,使之与参数 name 相同。
  • String getName()  返回该线程的名称。从Thread - 0 开始,编号依次累加
  • boolean isAlive()  测试线程是否处于活动状态。
  • void start()  使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

设置线程对象名称的两种方式:

  • Thread(String name)  子类需要提供String的带参构造
  • void setName(String name)  改变线程名称,使之与参数 name 相同。
// 对应第一种创建线程的方式
public
class MyThread extends Thread { public MyThread() { // 无参构造 super(); } public MyThread(String name) { // 有参构造 super(name); } @Override public void run() { //谁调用run方法,谁就是this, this可以省略 System.out.println(this.getName() + " 调用了run()方法"); } } // 测试类 public class Test { public static void main(String[] args) { // 方式一 MyThread thread = new MyThread("线程一"); System.out.println(thread.getName()); // 线程一 thread.start(); // 方式二 MyThread thread2 = new MyThread(); thread2.setName("线程2"); System.out.println(thread2.getName()); // 线程2 thread2.start(); } }
// 对应第二种创建线程的方式
public
class MyRunnable implements Runnable { @Override public void run() { Thread thread = Thread.currentThread();  //1)获取当前正在执行的线程对象的引用 System.out.println(thread.getName() + " 调用了run()方法"); } } // 测试类 public class Test { public static void main(String[] args) {
    //2) 创建实现类对象 MyRunnable runnable
= new MyRunnable(); //3)创建线程对象 Thread(Runnable target, String name)方法(常用) Thread t1 = new Thread(runnable,"线程一"); Thread t2 = new Thread(runnable, "t2");
    //4)开启线程 t1.start(); t2.start(); } }

 

posted @ 2022-07-05 15:59  鹿先森JIAN  阅读(164)  评论(0编辑  收藏  举报