多线程创建的四种方式

来源:互联网 发布:守望先锋生涯数据出错 编辑:程序博客网 时间:2024/06/05 19:11

多线程的创建之—-继承Thread类

继承Thread类。并重写run()方法,然后启动线程
1、自定义MyThread类,继承Thread类
2、在MyThread类中重写run方法
3、创建MyThread类的对象
4、启动线程对象(start方法是Thread类的方法)

1、举个小例子:
MyThread类:

public class MyThread extends Thread {    @Override    public void run() {        for (int i = 0; i < 100; i++) {            System.out.println(this.getName() + ":" + i);        }    }}

测试类:

public class MyThreadDemo {    public static void main(String[] args) {        MyThread myThread = new MyThread();                  //创建MyThread类的线程对象        MyThread myThread2 = new MyThread();                 //创建MyThread类的线程对象        myThread.start();                                    //启动线程        myThread2.start();                                   //启动线程    }}

控制台输出:只截取一部分,看个效果即可。因为数据量太大。

Thread-0:0Thread-1:0Thread-0:1Thread-1:1Thread-1:2


2、为什么我调用getName()方法后,它的名字显示的是Thread-的形式呢?
我们来看看源码:

private char name[];//MyThread 类会有一个默认无参构造,这个构造默认会默认调用父类Thread的无参构造public MyThread extends Thread{    public MyThread(){        super();    }}//第一步:public Thread() {    init(null, null, "Thread-" + nextThreadNum(), 0);}//第二步private static int threadInitNumber;                   //默认值是0private static synchronized int nextThreadNum() {   return threadInitNumber++;}//第二步private void init(ThreadGroup g, Runnable target, String name,                      long stackSize) {    init(g, target, name, stackSize, null);}//第三步private void init(ThreadGroup g, Runnable target, String name,                      long stackSize, AccessControlContext acc) {    //大部分代码我没粘贴过来,我只留了主要的代码,可以自己去看源码    this.name = name.toCharArray();}//第四步public final String getName() {   return String.valueOf(name);}

这样思路就该清晰了:
(1)、在MyThread类中调用getName()方法,这个方法在MyThread中是没有定义的,因此它调用的是父类的方法。
(2)、加载Thread()类,无参构造中,调用了init(四个参数),然后init(四个参数)又调用了init(五个参数),在init(五个参数)方法中,把this.name = name.toCharArray();把传进来的参数准换成char数组赋值给了全局的char[] name
(3)、在getName()方法中,把全局的char[] name转换为了String字符串,然后显示在界面上

3、但是Thread-这样的名字并不好区分和辨认,也没有实际的意义,因此我们会想到给自己的线程设定指定的名字。

public class MyThreadDemo {    public static void main(String[] args) {        //创建线程        MyThread myThread = new MyThread();        MyThread myThread2 = new MyThread();        //给线程设置名字        myThread.setName("这是第一个线程");        myThread2.setName("这是第二个线程");        myThread.start();        myThread2.start();    }}

那我们来看看setName()的源码到底是什么样的:我们可以发现setName()把传递过来的name参数准换位字符数组,然后getName()再把字符数组转换成字符串进行输出。

private char name[];public final void setName(String name) {   checkAccess();   this.name = name.toCharArray();}public final String getName() {   return String.valueOf(name);}


4、上面的是采用无参构造+setName()实现的,现在我们采用带参构造给线程起名字
MyThread类:

public class MyThread extends Thread {    public MyThread() {    }    //继承父亲的带参构造方法    public MyThread(String name) {        super(name);    }    @Override    public void run() {        for (int i = 0; i < 100; i++) {            System.out.println(this.getName() + ":" + i);        }    }}

测试类:

public class MyThreadDemo {    public static void main(String[] args) {        //创建线程,并且给线程起名字        MyThread myThread = new MyThread("这是第一个线程");        MyThread myThread2 = new MyThread("这是第二个线程");        myThread.start();        myThread2.start();    }}


5、获取main方法所在的线程对象的名称。(获取不是Thread类的子类的线程对象的名称)
public static Thread currentThread():返回对当前正在执行的线程对象的引用。

public class MyThreadDemo {    public static void main(String[] args) {        System.out.println(Thread.currentThread().getName());     //main    }}

多线程的创建之—-实现runable接口

1、自定义MyRunable类实现Runnable接口
2、在MyRunable类中重写run()方法
3、创建MyRunable类的对象
4、创建Thread类的对象,并把MyRunable的对象作为构造参数传递进去(因为只有Thread类才有start方法,因此Thread类有一个构造方法是,runnable对象作为参数传递进去创建一个thread对象的方法,这样由thread对象调用start方法)
MyRunnable类:

public class MyRunnable implements Runnable {    @Override    public void run() {        for(int i = 0;i < 100;i++){            //由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接使用。            System.out.println(Thread.currentThread().getName()+":"+i);;        }    }}

测试类:

public class MyRunnableDemo {    public static void main(String[] args) {        // 创建MyRunnable类的对象        MyRunnable mr = new MyRunnable();        // 创建Thread类的对象,并把MyRunnable类的对象作为构造参数传递        Thread t1 = new Thread(mr,"小骨");        Thread t2 = new Thread(mr,"玥公子");        t1.start();        t2.start();    }}

多线程的创建之—-使用Callable接口和Future接口(依赖于线程池存在的)(太复杂,不推荐使用)

从java5之后,java提供了Callable接口,Callable接口提供了一个call()方法可以作为线程的执行体,但call()方法比run()方法功能更强大,call()方法可以有返回值,call()方法可以声明抛出异常。

java5提供了Future接口来代表Callable接口里call()方法的返回值,并为Future接口提供了一个FutureTask实现类,该实现类中实现了Future接口,并实现了Runnable接口。可以作为Thread类的target.

但是Callable接口是依赖线程池存在的。
要了解线程池,可以去看这篇文章:http://blog.csdn.net/qq_36748278/article/details/78142968

//Callable接口:带泛型的接口//call()方法的返回值类型就是接口指定的泛型,如果不指定就是Object类型//依赖线程池操作public class MyCallable implements Callable<Integer>{    private int number;    public MyCallable(int number) {        this.number = number;    }    @Override    public Integer call() throws Exception {        int sum = 0;        for (int i = 0; i < number; i++) {            sum += i;        }        return sum;    }}
public class CallableDemo {    public static void main(String[] args) throws InterruptedException, ExecutionException {        // 创建线程池对象        ExecutorService pool = Executors.newFixedThreadPool(2);        // 可以执行Runnable对象或者Callable对象代表的线程        Future<Integer> future = pool.submit(new MyCallable(100));        Future<Integer> future2 = pool.submit(new MyCallable(200));        Integer i1 = future.get();        Integer i2 = future2.get();        System.out.println(i1 + "," + i2);        pool.shutdown();    }}

多线程的创建之—-匿名内部类实现多线程

匿名内部类的格式:(本质是创建该类或者接口的子类对象)
new 类名或接口名(){
     重写方法
}

public class ThreadDemo {    public static void main(String[] args) {        //继承Thread类来实现多线程        new Thread() {            @Override            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println(Thread.currentThread().getName() + ":" + i);                }            }        }.start();        //实现Runnable接口来实现多线程        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println("runnable" + ":" + i);                }            }        }){}.start();        //走子类对象thread,不走Runnable接口的        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println("runnable" + ":" + i);                }            }        }){            public void run() {                for (int i = 0; i < 100; i++) {                    System.out.println("thread" + ":" + i);                }            }        }.start();    }}
原创粉丝点击