Java多线程
创建多线程
- 继承Thread类,实现多线程
- java里面提供了一个java.lang.Thread的程序类,一个类只要继承此类就表示这个类为线程的主体类,然后覆写Thread类中的run()方法(public void run()),此方法就是线程的主方法。eg:
class MyThread extends Thread {//线程主体类
private String title;
public MyThread(String title) {
this.title = title;
}
@Override
public void run() {//线程的主体方法
for(int x = 0; x < 10 ; x++) {
System.out.println(this.title + "运行,x = " + x);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
new MyThread("线程A").start();
new MyThread("线程B").start();
new MyThread("线程C").start();
}
}
- 基于Runnable接口实现多线程
- 虽然可以通过Thread类的继承来实现多线程的定义,但是在Java程序里面对于继承永远都是存在有单继承局限的,所以在Java里面又提供有第二种多线程的主体定义结构形式:实现java.lang.Runnable接口;eg:
class MyThread implements Runnable {//线程主体类
private String title;
public MyThread(String title) {
this.title = title;
}
@Override
public void run() {//线程的主体方法
for(int x = 0; x < 10 ; x++) {
System.out.println(this.title + "运行,x = " + x);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
Thread threadA = new Thread(new MyThread("线程A"));
Thread threadB = new Thread(new MyThread("线程B"));
Thread threadC = new Thread(new MyThread("线程C"));
threadA.start();
threadB.start();
threadC.start();
}
}
可以发现从JDK1.8开始,Runnable接口使用了函数式接口定义,所以
也可以直接利用Lambda表达式进行线程类的实现定义。eg:
public class ThreadDemo {
public static void main(String[] args) {
for( int x = 0; x < 3 ; x ++) {
String title = "线程对象-" + x;
Runnable runnable = () ->{
for(int y = 0; y < 10 ; y ++) {
System.out.println(title + "运行,y = " + y);
}
};
new Thread(runnable).start();
}
}
}
在以后的开发中对于多线程的实现,优先考虑Runnable接口实现,并且永恒都是通
过Thread类对象启动多线程。多线程开发的本质实质上是在于多个线程可以进行统一资源的抢占,那么Thread主要描述的是线程,
那么资源的描述是通过Runnable完成的。
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源,注意每个线程都是用同一个实例化对象;eg:
class Thread2 implements Runnable{
private int count=15;
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "运行 count= " + count--);
try {
Thread.sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Thread2 my = new Thread2();
new Thread(my, "C").start();//同一个mt,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常
new Thread(my, "D").start();
new Thread(my, "E").start();
}
}
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
- Callable实现多线程
- Callbale定义的时候可以设置一个泛型,此泛型的类型就是返回数据的类型,这样的的好处是可以避免向下转行所带来的安全隐患。
- 线程执行完毕后,可以获取一个返回值
- eg:
class MyThread2 implements Callable<String> {
@Override
public String call() throws Exception {
for ( int x = 0 ; x < 10 ; x ++ ) {
System.out.println("******线程执行,x = " + x);
}
return "线程执行完毕!";
}
}
public class demo {
public static void main(String[] args) throws Exception{
FutureTask futureTask = new FutureTask(new MyThread2());
new Thread(futureTask).start();
System.out.println("线程返回值:" + futureTask.get());
}
}
- 线程池
-
使用线程池原因:经常创建销毁线程,耗资靡费,对性能影响很大。
-
原理:提前创建好多个线程,放入线程池,用时获取,用完放回。(数据库连接池)
-
优点:及时响应,降低资源耗费,便于管理
-
主要属性:corePoolSize:核心池的大小 maximumPoolSize:最大线程数 keepAliveTime:线程没有任务时最多保持多长时间后会终止
-
线程池API:ExecutorService 和 Executors
ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor. void execute(Runnable coommand):执行任务/命令,没有返回值,一般用来执行Runnable Futuresubmit(Callable task):执行任务,有返回值,一般又来执行Callable void shutdown():关闭连接池。 Executors.newCachedThreadPool() 创建一个可根据需要创建新线程的线程池 Executors.newFixedThreadPool(n) 创建一个可重用固定线程数的线程池 Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池 Executors.newScheduledThreadPool(n) 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
-
线程池构造批量线程代码:
-
/**
* 创建线程的方式四:使用线程池(批量使用线程)
*1.需要创建实现runnable或者callable接口方式的对象
* 2.创建executorservice线程池
* 3.将创建好的实现了runnable接口类的对象放入executorService对象的execute方法中执行。
* 4.关闭线程池
*
* */
class NumberThread implements Runnable{
@Override
public void run() {
for(int i = 0;i<=100;i++){
if (i % 2 ==0 )
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
class NumberThread1 implements Runnable{
@Override
public void run() {
for(int i = 0;i<100; i++){
if(i%2==1){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args){
//创建固定线程个数为十个的线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
//new一个Runnable接口的对象
NumberThread number = new NumberThread();
NumberThread1 number1 = new NumberThread1();
//执行线程,最多十个
executorService.execute(number1);
executorService.execute(number);//适合适用于Runnable
//executorService.submit();//适合使用于Callable
//关闭线程池
executorService.shutdown();
}
}
- 参考文章
https://blog.csdn.net/taojin12/article/details/85544403
https://blog.csdn.net/weixin_44797490/article/details/91006241