JavaSE多线程《二》

JavaSE多线程《一》回顾

三·多线程的常用操作方法

3.1 线程的命名于取得命名
多线程的运行状态是不确定的,所以对于多线程操作必须有一个明确标识出线程对象的信息,这个信息往往通过名称来描述。在Thread类中提供有如下的线程名称方法:

在这里插入图片描述

要想取得线程的对象,在Thread类中提供有一个方法取得当前线程对象:

/**
* Returns a reference to the currently executing thread object.
*
* @return the currently executing thread.
*/
public static native Thread currentThread();

下面请观察线程名取得的方法和设置线程方法名:

package com.revision.Thread;

public class SettingName implements Runnable {
    @Override
    public void run() {
        for(int i = 0; i <= 10; i++){
            System.out.println("当前线程为:" + Thread.currentThread().getName()
            + "   i = " + i);
        }
    }

    public static void main(String[] args) {
        SettingName sn = new SettingName();
        new Thread(sn).start();
        new Thread(sn).start();
        new Thread(sn,"name").start();
    }

}

运行结果为:

在这里插入图片描述

通过使用currentThread()方法 获取当前 线程 让后使用getName()方法获取正在运行的方法名。
可以发现,未设置名字的线程默认叫做 Thread-0和Thread-1 而设置过名字的线程 name 显示了设置过的名字

需要注意的是,线程名字如果要设置请避免重复,同时中间不要修改。

观察以下代码

class MyThread implements Runnable {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getName());
		}
}
public class TestDemo {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.run(); // 直接通过对象调用run()方法
new Thread(mt).start(); // 通过线程调用
		}
}

通过以上程序我们发现,主方法本身就是一个线程,所有的线程都是通过主线程创建并启动的。

在这里插入图片描述

疑问:进程在哪?

实际上每当使用了java命令去解释程序的时候,都表示启动了一个新的JVM进程。而主方法只是这个进程上的一个线程而已。

3.2 线程休眠(sleep方法)

线程休眠:指的是让线程暂缓执行一下,等到了预计时间之后再恢复执行

线程休眠会交出CPU,让CPU去执行其他的任务。但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法其他线程也无法访问这个对象.

让我们看看sleep()方法:

public static native void sleep(long millis) throws InterruptedException

休眠时间 用的是 毫秒 为单位

代码示例

package com.revision.Thread;

public class TestSleep implements Runnable {
    @Override
    public void run() {
        for(int i = 0; i <= 10;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("当前线程:" + Thread.currentThread().getName() + " i = " + i);
        }
    }

    public static void main(String[] args) {
        TestSleep ts = new TestSleep();
        new Thread(ts).start();
        new Thread(ts).start();
        new Thread(ts).start();

    }

}

运行结果:
在这里插入图片描述

结果是:每1s有三个线程执行。
通过代码观察会错误的认为这三个线程是同时休眠的,但是千万要记住,所有的代码是依次进入到run()方法中的。
真正进入到方法的对象可能是多个,也可能是一个。进入代码的顺序可能有差异,但是总体的执行是并发执行。

3.3 线程让步(yield()方法)

暂停当前正在执行的线程对象,并执行其他线程。

意思就是调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会

注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

sleep是线程睡眠到期自动苏醒,并返回到可运行状态(就绪),不是运行状态。

代码示例:

class MyThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 3 ; i++) {
Thread.yield();
System.out.println("当前线程:" + Thread.currentThread().getName()+" ,i = "
+i);
}
}
}
public class Test {
public static void main(String[] args){
MyThread mt = new MyThread();
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();
}
}

3.4 join()方法

**等待该线程终止。**意思就是如果在主线程中调用该方法时就会让主线程休眠,让调用该方法的线程run方法先执行完毕之后在开始执行主线程。

示例:

package com.revision.Thread;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


class MyJoin implements Runnable{
    @Override
    public void run() {
        try {
            System.out.println("主线程睡眠前的时间:");
            TestJoin.printTime();
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName());
            System.out.println("睡眠结束的时间:");
            TestJoin.printTime();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class TestJoin {
    public static void main(String[] args) throws InterruptedException {
        MyJoin mj = new MyJoin();
        Thread thread = new Thread(mj,"子线程A");
        thread.start();
        System.out.println(Thread.currentThread().getName());
        thread.join();
        System.out.println("代码结束!");
    }
    public static void printTime(){
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = format.format(date);
        System.out.println(time);
    }
}

运行结果为

在这里插入图片描述

也就是 先获取了主线程的名字,然后调用该方法的线程A开始运行,等到线程A运行完了 随后继续运行主线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值