Java---11---多线程的两种创建方式

多线程的两种创建方式:

下面这些东西是API文档中的:



public class Thread

extends Object

implements Runnable

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。 

每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。 

当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止: 

· 调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。 

· 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。 

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成: 


class PrimeThread extends Thread
{
    long minPrime;
    PrimeThread(long minPrime)
    {
        this.minPrime = minPrime;
    }

    public void run()
    {
        // compute primes larger than minPrime
        . . .
    }
}


 

然后,下列代码会创建并启动一个线程: 

    

PrimeThread p = new PrimeThread(143);
p.start();

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示: 

 

class PrimeRun implements Runnable
{
    long minPrime;
    PrimeRun(long minPrime)
    {
        this.minPrime = minPrime;
    }

    public void run()
    {
        // compute primes larger than minPrime
        . . .
    }
}


 

然后,下列代码会创建并启动一个线程: 

     

PrimeRun p = new PrimeRun(143);
new Thread(p).start();

每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。

---------------------------------------------

线程的创建方式:

1.继承Thread

2.实现Runnable

 

第一种方式:继承Thread类

实现步骤:

1.自定义类继承Thread

2.复习Thread中的run()方法

3.创建该类的对象,调用start()方法,开启线程并调用run方法

 

简单实现:


class MyThread extends Thread
{
    public void run ()
    {
        for (int i = 0; i < 100; i++)
        {
            System.out.println("MyThread.run()..."+i);
        }
    }
}
public class THREAD
{
    public static void main (String[] args)
    {
        MyThread a = new MyThread();
        a.start();
        for (int j = 0; j < 100; j++)
        {
            System.out.println("THREAD.main()----"+j);
        }
    }
}


多运行几次会发现:

i所在的线程和j所在的线程会交替运行

但是每次运行的结果却是不一样的

这就是多线程的随机性

 

为什么要覆盖run方法?

Thread 用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码

该存储功能就是run方法。

 

第二种创建方式:实现Runnable

Runnable是一个简单的接口,该接口中只有一个抽象方法:run方法。

实现步骤:

1.定义一个实现Runnable接口的类

2.覆盖run方法

3.创建该类对象,并以该类对象为参数创建Thread类的对象,从而创建了一个线程

4.调用start方法,开启线程并调用run方法。

 

简单创建:


class MyThread implements Runnable
{
    public void run ()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println("MyThread.run()..."+i);
        }
    }
}
public class THREAD
{
    public static void main (String[] args)
    {
        MyThread a = new MyThread();
        Thread a1 = new Thread(a);
        Thread a2 = new Thread(a);
        Thread a3 = new Thread(a);
        Thread a4 = new Thread(a);

        a1.start();
        a2.start();
        a3.start();
        a4.start();
    }
}


该例子中创建了四个线程,能够实现四个线程的交替运行,但是却看不出是哪个线程执行的,

调用Thread类中的getName方法可以解决这个问题


System.out.println(Thread.currentThread().getName()+"..."+i);

currentThread():获取当前线程对象

线程的名字 

Thread-0

Thread-1

...

线程都有自己默认的名称,Thread-编号  编号从0开始

也可以自己定义线程的名称。


class MyThread implements Runnable
{
    private String name;
    public MyThread(String name)
    {
        this.name = name;
    }

    public String GetName()
    {
        return name;
    }
    public void run ()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println(this.GetName()+"..."+i);
        }
    }
}
public class THREAD
{
    public static void main (String[] args)
    {
        MyThread a = new MyThread("My");
        MyThread b = new MyThread("Your");
        Thread a1 = new Thread(a);
        Thread a2 = new Thread(b);

        a1.start();
        a2.start();

    }
}


如果用的是 继承Thread类的方式 直接用super就可以,

因为Thread类中有getName这个方法,通过构造函数初始化线程,然后直接调用getName方法就行。


class MyThread extends Thread
{
    private String name;
    public MyThread(String name)
    {
        super(name);
    }

//	public String GetName(){
//		return name;
//	}
    public void run ()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName()+"..."+i);
        }
    }
}
public class THREAD
{
    public static void main (String[] args)
    {
        MyThread a = new MyThread("My");
        MyThread b = new MyThread("Your");
//		Thread a1 = new Thread(a);
//		Thread a2 = new Thread(b);

        a.start();
        b.start();

    }
}



两种方式的区别:

第一种:继承Thread的方法:

1.缺点:Java语言只允许单继承,所以该类继承了Thread之后就不可以再继承其他的类了

2.优点:编写简单。

第二种:实现Runnable接口的方式:

1.缺点:编写稍显复杂

2.优点:

a) 避免由于单继承带来的局限性

b) 有利于代码的健壮性,代码能够被多个线程共享,代码与数据是独立的

代码存放的位置:

继承Thread方式:线程代码存放于Thread子类的run方法中

实现Runnable方式:线程代码存放于接口子类的run方法中。



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。