Java多线程(二)

二、线程的创建

Java编程语言的JVM虚拟机允许程序运行多个线程,具体是通过java.lang.Thread 类来体现。

Thread类的特点:

  • 将需要线程执行的程序编写在Thread类的run()方法中,所以将run()的方法体称为线程体;

  • 通过Thread类对象的start()方法启动该线程,并不是直接调用run()本身。

2.1 Thread构造器

在不包含线程组构造器的情况下,Thread类有四个构造器

public Thread(); // 分配一个Thread对象
public Thread(String name) // 分配一个Thread对象,指定Thread名称
public Thread(Runnable target) // 指定创建线程的目标对象,它实现了Runnable接口中的run方法
public Thread(Runnable target, String name) // 指定创建线程的目标对象,它实现了Runnable接口中的run方法,指定Thread线程名称

2.2 创建线程的方式

在Java SDK中有四种创建新线程的方式,分为两个阶段

  • JDK5.0之前有两种方式

  1. 通过继承Thread类的方式;

  2. 通过实现Runnable接口的方式。

方式一、继承Thread类

  1. 定义子类继承Thread类;

  2. 子类中重写Thread类的run()方法;

  3. 创建Thread类子类的对象,即线程对象;

  4. 调用线程对象的start()方法,启动线程,执行run()

方式二、实现Runnable接口

  1. 定义子类实现Runnable接口;

  2. 子类中重写Runnable接口中的run方法;

  3. 通过Thread类的构造器,将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中;

  1. 调用线程的start()方法,启动线程,调用了接口子类的run()方法。

  • JDK5.0新增两种方式

  1. 通过实现Callable接口的方式;

  2. 通过线程池的方式。

方式三、实现Callable接口

  1. 定义子类实现Callable接口;

  2. 子类中重写Callable接口中call()方法;

  3. 通过FutureTask类的构造器,将Callable接口的子类对象作为实际参数传递给FutureTask类的构造器中;

  4. 通过Thread类的构造器,将FutureTask类对象作为实际参数传递给Thread类的构造器中;

  5. 通过线程的start()方法,启动线程,回调call()方法。

方式四、线程池使用

  1. 创建ExecutorService接口实现类的一个对象,即具体的线程池对象;

  2. 调用execute()方法将Runnable接口实现类对象传入参数,执行run()方法;

  3. 调用submit()方法将Callable接口实现类对象传入参数,执行call()方法;

  4. 调用shutdown()方法,关闭线程池。

2.3 创建线程案例

  • 准备工作

需求描述:计算大于给定数字num的最小质数 

// 工具方法:判断是否是质数
private Boolean isPrime(long number) {
    for (int i = 2; i * i <= number; i++) {
        if (number % i == 0) {
            return false;
        }
    }
    return true;
}
  • 继承Thread类方式

class PrimeThread extends Thread {
    
    private long minPrime;
    
    public PrimeThread(long minPrime) {
        this.minPrime = minPrime;
    }
​
    @Override
    public void run() {
        // compute primes larger than minPrime
        long temp = minPrime + 1;
        while (!isPrime(temp)) {
            temp++;
        }
        System.out.println("当前线程名称:" + Thread.currentThread().getName() + ",初始结果:" + minPrime + ",结果数据:" + temp);
    }
}
​
// 启动线程
PrimeThread p1 = new PrimeThread(21);
//①启动当前线程;②调用当前线程run()方法
p1.start();
  • 实现Runnable接口

class PrimeRun implements Runnable {
    private long minPrime;
​
    public PrimeRun(long minPrime) {
        this.minPrime = minPrime;
    }
​
    @Override
    public void run() {
        // compute primes larger than minPrime
        long temp = minPrime + 1;
        while (!isPrime(temp)) {
            temp++;
        }
        System.out.println("当前线程名称:" + Thread.currentThread().getName() + ",初始结果:" + minPrime + ",结果数据:" + temp);
​
    }
}
​
// 启动线程
PrimeRun p1 = new PrimeRun(11);
new Thread(p1).start();
  • 实现Callable接口

class PrimeCall implements Callable<Long> {
​
    private long minPrime;
​
    public PrimeCall(long minPrime) {
        this.minPrime = minPrime;
    }
​
    @Override
    public Long call() throws Exception {
        long temp = minPrime + 1;
        while (!isPrime(temp)) {
            temp++;
        }
        System.out.println("当前线程名称:" + Thread.currentThread().getName() + ",初始结果:" + minPrime + ",结果数据:" + temp);
        return temp;
    }
}
​
// 启动线程
PrimeCall primeCall1 = new PrimeCall(345);
FutureTask<Long> futureTask = new FutureTask<>(primeCall1);
Thread t1 = new Thread(futureTask);
t1.start();
  • 线程池方式

// 启动线程
ExecutorService service = Executors.newFixedThreadPool(3);
service.execute(new PrimeRun(234));
service.submit(new PrimeCall(32));
service.shutdown();

2.4 Thread常用方法

  • Thread的常用方法

public synchronized void start() // 启动线程,执行run()方法
public void run() // 线程调度时执行的具体操作
public void setName(String name) // 设置该线程名称
public String getName() // 返回线程的名称
public static native Thread currentThread() // 获取当前线程对象,相当于this
public static native void yield() // 线程让步,暂停当前正在执行线程,将执行机会让给优先级相同或者更高的线程
public final void join() throws InterruptedException 
// 在程序的执行过程中,调用某个某个线程的join()方法,则调用线程阻塞,直到join()方法所在线程执行结束
// 例如Main线程中调用t1线程,调用t1.join(),则等待t1线程执行结束之后,继续执行Main线程
public static native void sleep(long millis) throws InterruptedException
// 令当前线程在指定时间内放弃CPU的控制权(指定时间:毫秒)
public final native boolean isAlive() // 判断线程是否还活着
  • 线程的优先级

// 线程的优先级等级
    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;

// 线程优先级涉及的方法
    public final void setPriority(int newPriority) // 改变线程的优先级 
    public final int getPriority() // 线程优先值

说明:

  1. 线程创建时继承父线程的优先级;

  2. 低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用;

  3. 调度策略,高优先级使用优先调度的抢占式策略,同级优先级使用先进先出的策略。

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值