java线程基本使用(创建线程)

java线程基本使用(创建线程)

创建线程的两种方式

1.继承Thread类,重写run方法

演示:
1.编写程序,开启一个线程,该线程每隔1秒。在控制台输出“喵喵,我是小猫咪”
package threaduse;

public class Thread01 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.start();//启动线程-> 最终会执行 cat 
    }
}

//说明
//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用
//2. 我们会重写 run 方法,写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的 run 方法
/*
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
*/
@SuppressWarnings({"all"})
class Cat extends Thread{
    @Override
    public void run() {
        while(true){
            System.out.println("喵喵,我是小猫");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
2.对上题进行改进:当输出80次后,结束进程
package threaduse;

public class Thread01 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.start();//启动线程-> 最终会执行 cat
    }
}

//说明
//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用
//2. 我们会重写 run 方法,写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的 run 方法
/*
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
*/
@SuppressWarnings({"all"})
class Cat extends Thread{
    @Override
    public void run() {
        int count=1;
        while(true){
            System.out.println("喵喵,我是小猫"+count);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(count!=80){
                count++;
            }
            else{
                break;
            }
        }
    }
}
3.使用 JConsole 监控线程执行情况
package threaduse;

public class Thread01 {
    public static void main(String[] args) throws InterruptedException {
        Cat cat = new Cat();
        cat.start();//启动线程-> 最终会执行 cat
        for (int i = 0; i < 60; i++) {
            System.out.println("主线程i="+i);
            Thread.sleep(1000);
        }
    }
}

//说明
//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用
//2. 我们会重写 run 方法,写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的 run 方法
/*
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
*/
@SuppressWarnings({"all"})
class Cat extends Thread{
    @Override
    public void run() {
        int count=1;
        while(true){
            System.out.println("喵喵,我是小猫"+count);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(count!=80){
                count++;
            }
            else{
                break;
            }
        }
    }
}

主线程挂了,子线程不一定结束(通过以上例子说明主线程main退出后,子线程Thread-0继续执行)

为什么是调用start方法而不是run方法
案例
package threaduse;

public class Thread01 {
    public static void main(String[] args) throws InterruptedException {
        Cat cat = new Cat();
//        cat.start();//启动线程-> 最终会执行 cat

        //读源码
/*
    (1)
        public synchronized void start() {
            start0();
        }
    (2)
        //start0() 是本地方法,是 JVM 调用, 底层是 c/c++实现
        //真正实现多线程的效果, 是 start0(), 而不是 run
            private native void start0();
*/

        cat.run();
        //cat.run();//run 方法就是一个普通的方法, 没有真正的启动一个线程,就会把 run 方法执行完毕,才向下执行
        //说明: 当 main 线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行
        //这时 主线程和子线程是交替执行
        System.out.println("主线程继续执行" + Thread.currentThread().getName());//名字 main
        for (int i = 0; i < 60; i++) {
            System.out.println("主线程i="+i);
            Thread.sleep(1000);
        }
    }
}

//说明
//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用
//2. 我们会重写 run 方法,写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的 run 方法
/*
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
*/
@SuppressWarnings({"all"})
class Cat extends Thread{
    @Override
    public void run() {
        int count=1;
        while(true){
            System.out.println("喵喵, 我是小猫咪" + count + " 线程名=" + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(count!=80){
                count++;
            }
            else{
                break;
            }
        }
    }
}
解释:

1.首先 start 方法调用 start0()方法

public synchronized void start(){
	.....
	start0();
	.....
}
  1. start0()是本地方法,是 JVM 调用,底层是c/c++实现

    真正实现多线程的效果是 start0(),而不是run

    private native void start0();

  2. start()调用start0()方法后,该线程并不一定立马执行,只是将线程变成可运行状态。具体说明时候执行,取决于CPU,由CPU统一调度

2.实现Runnable接口,重写run方法

说明:

**1.**java是单继承,在某些情况下一个类可能继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能了

**2.**java设计者提供了另一个方式创建线程,就是通过实现Runnable接口来创建线程

应用案例:

编写程序,可以每隔1秒,在控制台输出“小狗汪汪叫”,当输出10次后,自动退出。使用实现Runnable接口的方式实现

package threaduse;

public class Thread02 {
    public static void main(String[] args) {
        Dog dog = new Dog();
//        dog.start();这里不能调用start
        //创建了Thread对象,把dog对象,放入Thread
        Thread thread = new Thread(dog);
        thread.start();
    }
}
@SuppressWarnings({"all"})
class Dog implements Runnable{
    private int count=0;
    @Override
    public void run() {
        while(true){
            System.out.println("小狗汪汪叫..."+(++count)+"---"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(count==10){
                break;
            }
        }
    }
}

编写一个程序,创建两个线程,一个线程每隔1秒输出“hello Thread”,输出10次退出,一个每隔1秒输出“hi”,输出5次退出

package threaduse;

public class Thread03 {
    public static void main(String[] args) {
        T1 t1 = new T1();
        T2 t2 = new T2();
        Thread thread0 = new Thread(t1);
        Thread thread1 = new Thread(t2);
        thread0.start();
        thread1.start();
//        new Thread(new T1()).start();//简写
    }
}
class T1 implements  Runnable{
    private int count=0;
    @Override
    public void run() {
        while(true){
            System.out.println("hello Thread"+(++count)+"---"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(count==10){
                break;
            }
        }
    }
}
class T2 implements  Runnable{
    private int count=0;
    @Override
    public void run() {
        while(true){
            System.out.println("hi"+(++count)+"---"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(count==5){
                break;
            }
        }
    }
}

继承Thread vs 实现Runnable 的区别

**1.**从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别。

**2.**实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制,建议使用Runnable

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alonzo de blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值