likes
comments
collection
share

【Java并发编程】创建线程的几种方式你都知道吗?

作者站长头像
站长
· 阅读数 17

创建线程的几种方法

继承Thread类创建线程

public class Creation {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("running...");
    }
}

实现Runnable接口创建线程

public class Creation {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread thread = new Thread(myThread);
        thread.start();
    }
}

class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println("running...");
    }
}

Thrad和Runnable的关系

Thread实现了Runable接口。

public class Thread implements Runnable {
    
    private Runnable target;
    
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    
    @Override
    public void run() {
        if (target != null) {
            // 1.要么重写 Runnable 的 run 方法。
            // 2.要么传入 Runnable 的实现类,调用其 run 方法。
            target.run();
        }
    }
}

Thread与Runable创建线程区别

Runnable可理解为资源,Thread理解为处理资源的线程。

1、继承Thread类的方式,new了三个Thread,实际上是有300张票。

2、实现Runnable接口的方式,new了三个Thread,实际上是有100张票。

3、也就是说实现Runnable接口的线程中,成员属性是所有线程共有的。但是继承Thread类的线程中,成员属性是各个线程独有的,其它线程看不到,除非采用static的方式才能使各个线程都能看到。

4、就像上面说的Runnable相当于资源,Thread才是线程。用Runnable创建线程时,new了多个Thread,但是传进去的参数都是同一个Runnable(资源)。用Thread创建线程时,就直接new了多个线程,每个线程都有自己的Runnable(资源)。在Thread源码中就是用target变量(这是一个Runnable类型的变量)来表示这个资源。

5、同时因为这两个的区别,在并发编程中,继承了Thread的子类在进行线程同步时不能将成员变量当做锁,因为多个线程拿到的不是同一把锁,不过用static变量可以解决这个问题。而实现了Runnable接口的类在进行线程同步时没有这个问题。

class Window extends Thread{

    private  int ticket = 100;
    @Override
    public void run() {

        while(true){

            if(ticket > 0){
                System.out.println(getName() + ":卖票,票号为:" + ticket);
                ticket--;
            }else{
                break;
            }

        }

    }
}


public class WindowTest {
    public static void main(String[] args) {
        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();


        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}
class Window1 implements Runnable{

    private int ticket = 100;

    @Override
    public void run() {
        while(true){
            if(ticket > 0){
                System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
                ticket--;
            }else{
                break;
            }
        }
    }
}


public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }

}

实现Callable接口创建线程

package sort.impl.juc;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * @author WanJie
 * @since 2023-08-09 11:29
 */
public class Creation {
    public static void main(String[] args) {
        FutureTask<String> futureTask = new FutureTask<String>(new MyThread());
        Thread thread = new Thread(futureTask);
        thread.start();
    }
}

class MyThread implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("running");
        return "0K";
    }
}