Java SE——创建线程的四种方式

 

创建线程的方式有四种:

1.继承Thread类

2.实现Runnable接口

3.实现Callable接口

4.使用线程池

在这四种方法中,根据《Effective Java》一书中指出优先使用线程池

在继承Thread类和实现Runnable接口两种方法中,使用Runnable接口更加推荐(不会有单继承局限的问题)

若想要线程最终返回结果,使用实现Callable接口(只有这种方式有返回结果)

1.继承Thread类创建线程

新建一个线程最简单的方法就是直接继承Thread类,而后覆写该类中的run()方法,但是开启多线程还是要调用start()方法

(1)新建一个线程,使用run方法

package Practise;
class MyThread extends Thread//线程主类
{
	private String title;
	public MyThread(String title)
	{
		this.title=title;
	}
	
	public void run() {//所有线程从这里开始执行
		for(int i=0;i<10;i++)
		{
			System.out.println(this.title+",i="+i);
		}
		
	}
}
public class Test1
{
	public static void main(String[] args) {
		MyThread myThread1=new MyThread("thread1");
		MyThread myThread2=new MyThread("thread2");
		MyThread myThread3=new MyThread("thread3");
		myThread1.run();
		myThread2.run();
		myThread3.run();		
	}
}

 

(2)启动多线程是使用start方法,不是run方法

public class Test1
{
	public static void main(String[] args) {
		MyThread myThread1=new MyThread("线程1");
		MyThread myThread2=new MyThread("线程2");
		MyThread myThread3=new MyThread("线程3");
		myThread1.start();
		myThread2.start();
		myThread3.start();
		
	}
}

多线程每次执行的结果都不同

 

2.实现Runnable()接口创建线程

使用Thread类创建线程会产生单继承局限的问题,因此实现Runnable接口就很好的解决了这个问题,但是新的问题又产生了,在Runnable接口中没有start()方法,那么创建的线程就没有办法来启动,但是Thread类中的构造方法又很好的解决了这个问题

public Thread(Runnable target)

(1)利用Runnable接口来实现线程主体类

class MyThread implements Runnable{
	private String title;
	public MyThread(String title ) {
		// TODO Auto-generated constructor stub
		this.title=title;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<10;i++)
		{
			System.out.println(this.title+",i="+i);
		}
	}
	
}
public class Test1
{
	public static void main(String[] args) {
		MyThread myThread1=new MyThread("线程1");
		MyThread myThread2=new MyThread("线程2");
		MyThread myThread3=new MyThread("线程3");
		new Thread(myThread1).start();
		new Thread(myThread2).start();
		new Thread(myThread3).start();//启动多线程
	}
}

 

(2)使用匿名内部类进行Runnable对象创建

public class Test1
{
	public static void main(String[] args) {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("Hello World");
			}
		}).start();
	}
}

 

(3)使用Lamdba表达式进行Runnable对象创建

public class Test1
{
	public static void main(String[] args) {
		Runnable runnable=()->System.out.println("Hello world");
		new Thread(runnable).start();
	}
}

 

Thread与Runnable区别

        1)Runnable实现多线程可以避免单继承局限

        2)在定义Thread类时,Thread类是Runnable的接口子类,因此在实现Thread类时,一定覆写了Runnable接口的run()方法

        3)使用Runnable实现的多线程的程序类可以更好的描述出程序共享的概念(Thread也可以,只不过Runnable更好一些)

线程类的继承结构——代理模式

 

使用Thread实现数据共享

启动三个线程实现卖票处理。结果变为了卖各自的票

class MyThread extends Thread {
    private int ticket = 10;

    public void run() {
        while (this.ticket > 0) {
            System.out.println("剩余票数" + this.ticket--);
        }
    }
}

public class Test1 {
    public static void main(String[] args) {
        System.out.println("用Thread实现数据共享");
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
    }
}
 

 

而使用Runnable实现共享

Runnable实现的多线程的程序类可以更好的描述出程序共享的概念

class MyThread2 implements Runnable
{
	private int ticket=10;
	public void run() {
		while(this.ticket>0)
		{
			System.out.println("剩余票数"+this.ticket--);
		}
	}
}

public class Test1
{
	public static void main(String[] args) {
		System.out.println("使用Runnable实现共享");
		MyThread2 mThread2=new MyThread2();
		new Thread(mThread2).start();
		new Thread(mThread2).start();
	}
}

 

 

 

3.实现Callable接口创建线程

由于Runnable中的run()方法没有返回值,它的设计也遵循了主方法的设计原则:线程开始了就别回头。但是很多时候需要一些返回值,例如某些线程执行完成后可能带来一些返回结果,这种情况下就只能利用Callable来实现多线程

使用Callable定义线程主体类

package Practise;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

class MyThread implements Callable<String>
{
	private int ticket=10;
	public String call() throws Exception
	{
		while(this.ticket>0)
		{
			System.out.println("剩余票数"+this.ticket--);
		}
		return "票卖完了";
	}
}
public class Test1
{
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		FutureTask<String> task=new FutureTask<>(new MyThread());
		new Thread(task).start();
		new Thread(task).start();
		System.out.println(task.get());
		
	}
}

4.使用线程池创建线程

线程池是指多个线程封装在一起的操作

线程池相关操作都在java.util.concurrent包中进行

(1)核心接口(两个)及创建线程池的方法(4个)

1)普通线程池:

public interface ExecutorService extends Executor

--创建无大小限制的线程池

public static ExecutorService newCachedThreadPool()

--创建固定大小的线程池

public static ExecutorService newFixedThreadPool(int nThreads)

--单线程池

public static ExecutorService newSingleThreadExecutor()

2)调度线程池:

public interface ScheduledExecutorService extends ExecutorService

--创建定时调度池

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

(2)使用线程池的好处:

多个线程按照组的模式进行程序的处理,这样在逻辑复杂的环境下性能会有很好的提升

 

创建与大小限制的线程池

public class Test {
    public static void main(String[] args) {
// 创建了一个线程池模型,现在里面没有线程
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int index = i; // 保存i的值
            newCachedThreadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " ,i = " + index);
                } // 执行线程操作
            });
        }
        newCachedThreadPool.shutdown(); // 关闭线程池
    }
}

   创建单线程线程池

public class Test {
    public static void main(String[] args) {
// 创建了一个线程池模型,现在里面没有线程
// 单线程对象线程池
        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            int index = i; // 保存i的值
            newSingleThreadExecutor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " ,i = " + index);
                } // 执行线程操作
            });
        }
        newSingleThreadExecutor.shutdown(); // 关闭线程池
    }
}

创建固定大小线程池

public class Test {
    public static void main(String[] args) {
// 创建了一个线程池模型,现在里面没有线程
// 创建只有固定线程数量的线程池
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            int index = i; // 保存i的值
            newFixedThreadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " ,i = " + index);
                } // 执行线程操作
            });
        }
        newFixedThreadPool.shutdown(); // 关闭线程池
    }
}

创建定时调度池

public class Test {
    public static void main(String[] args) {
// 创建一个具备两个线程大小的定时调度线程池
        ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2);
        for (int i = 0; i < 10; i++) {
            int index = i;
// 表示3s后开始执行,每间隔2s执行一次
            newScheduledThreadPool.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " , i = " + index);
                }
            }, 3, 2, TimeUnit.SECONDS);
        }
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值