【多线程2】多线程的创建

创建线程

当我们理解了进程与线程之间的联系和区别之后,我们就可以用代码进行线程的创建了。因为java的JVM虚拟机已经把操作系统的原生API(C语言)给封装好了,所以我们只需要学习Java提供的对操作系统进行调用的API就好了。通过调用JVM封装的操作系统的API我们就可以进行多线程编程了。

我们学习多线程编程首先就是要学会如何创建一个线程。

jconsole工具的使用说明

首先为大家介绍以下jconsole工具,这个工具是jdk自带的,用来查看咱们运行的程序中有多少个线程。

大家可以根据以下目录以及自己电脑的实际安装情况找到这个工具。

C:\Program Files\Android\jdk\jdk-8.0.302.8-hotspot\jdk8u302-b08\bin

如果实在不知道自己的JDK安装在哪里了,我们也可以通过Win+R打开运行,输入jconsole直接打开jconsole工具

 前提是要配好环境变量。

运行jconsole后会出现这个界面:

我们先编写一个简单的程序。

 图中这段进程是jconsole自己的线程。

 这段进程则是idea的进程,jconsole是查看java程序进程的,所以证明了jconsole和idea都是用java语言编写的。

而第三个Main进程则是我们写的这个简短的程序的进程,我们选中Main,点击链接,再选择线程。

 

我们可以看到,左下角线程框里面列出了Main进程里面的所有线程,其中main线程是我们的主线程,也就是我们程序执行时创建的线程,因为我们这段程序中没有创建新的线程,所以我们的线程框中只有main线程是我们自己创建的,其他的线程都是JVM自带的线程,我们现阶段不需要了解。

通过学习jconsole工具,我们可以通过使用这个工具进行程序中线程的查看,现在我们就可以创建新的线程了。

创建一个新线程。

创建一个新的线程一共有五种方法。

1、继承Thread类,重写run()方法

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("hello thread");;
    }
}
public class Thread1 {
    public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();
        System.out.println("hello main");
    }
}

2、实现Runable接口

class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("hello Thread");
    }
}
public class Thread2 {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        System.out.println("hello main");
    }
}

3、使用匿名内部类继承Thread

public class Thread3 {
    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public void run() {
                System.out.println("hello thread");
            }
        };
        thread.start();
        System.out.println("hello main");
    }
}

4、使用匿名内部类实现Runable

public class Thread4 {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello Thread");
            }
        });
        thread.start();
        System.out.println("hello main");
    }
}

5、使用Lambda表达式

public class Thread5 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            System.out.println("hello Thread");
        });
        thread.start();
        System.out.println("hello main");
    }
}

代码解释

现在我们以继承Thread类,重写run方法为例解释一下多线程代码。

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("hello thread");;
    }
}
public class Thread1 {
    public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();
        System.out.println("hello main");
    }
}

首先,Java操作多线程的时候最核心的类就是Thread类,Thread使用的时候有几个特性需要我们大家明白。

(1)、使用Thread类不需要import任何的包,因为它包含在java.lang下面的,与之相同的还有Integer,String,StringBuilder,StringBuffer之类的类,也都不需要import任何的包。

(2)、我们创建了一个MyThread的类继承Thread,重写其中的run方法,run方法中的代码就是我们即将开启的新线程中要执行的代码。

(3)、我们创建一个线程对象(thread)的时候并不是就意味着开始执行了另一个线程,当我们开始调用start方法的时候才是真正的启动了一个新的线程。调用start方法就是调用操作系统的API通过操作系统内核开始创建了一个新的PCB,并且要把执行的指令也交给PCB,当PCB被调用到CUP上执行的时候,也就执行到了线程中的run方法了。

(4)、run方法不是由主线程调用的,而是主线程调用start方法,由start方法启动一个新的线程,这个新的线程会去执行run中的方法。

(5)、run方法执行完毕之后就会即刻把我们先创建的线程销毁。

我们需要明确一点的是,thread.start方法是通过主线程启动了一个新的线程,所以我们在thead.start 之后其实是有两个线程进行运行的,而且这两个线程是同时执行,不分先后的。

 


线程的抢占式执行

抢占式执行就是两个程序并发执行的时候,这两个线程就会抢占CPU资源,这样的抢占方式可以看作是随机的,我们可以用这样的程序来验证两个线程抢占式执行的方式。

import static java.lang.Thread.sleep;

class MyThread extends Thread{
    @Override
    public void run() {
        while(true){
            try {
                sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("hello thread");    
        }
        
    }
}
public class Thread1 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new MyThread();
        thread.start();
        while(true){
            sleep(100);
            System.out.println("hello main");    
        }
        
    }
}

我们无限的循环两个线程的打印程序,如果是抢占式执行那么两端程序一定是某一段时间执行“hello main”或者某一段时间执行“hello Thread”。

 结果可以看到,因为抢占式执行,两段程序不断地抢占CPU资源,造成了交替执行两端程序的结果。

现在我们看一下两端不断执行的线程在jconsole上的运行情况。

运行程序,链接好进程,再查看进程中的线程。

 

 

 其中main是主线程,而Thread-0就是我们通过thread.start创建的线程。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值