多线程-1:创建线程的几种方式

注1:总共就4种方式创建线程

注2:
Thread.currentThread() : 得到当前的线程对象(当前是哪个线程在执行这段代码)
Thread.currentThread().getName() : 得到当前线程对象的名字

关于创建线程的文章
https://blog.csdn.net/weixin_41891854/article/details/81265772
https://blog.csdn.net/cai13070139328/article/details/99079045

1.继承Thread类创建线程(由于Java单继承的特性,这种方式用的比较少,因为你一旦继承Thread类了,就不可以继承其他类了, 只有这唯一的缺点)

  1. run()方法是由jvm创建完本地操作系统级线程后回调的方法,不可以手动调用(否则就是普通方法: 详解https://www.zhihu.com/question/428459479)

方式一:继承于Thread类

  1. 创建一个继承于Thread类的子类
  2. 重写Thread类的run() --> 将此线程执行的操作声明在run()中
  3. 创建Thread类的子类的对象
  4. 通过此对象调用start()

实例:
//1. 创建一个继承于Thread类的子类
class MyThread extends Thread {
//2. 重写Thread类的run()
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + “:” + i);//获取当前线程名字
}
}
}
}

public class ThreadTest {
public static void main(String[] args) {
//3. 创建Thread类的子类的对象
MyThread t1 = new MyThread();

    //4.通过此对象调用start():①启动当前线程 ② 调用当前线程的run()
    t1.start();
    //问题一:我们不能通过直接调用run()的方式启动线程。
    // t1.run();

    //问题二:再启动一个线程,遍历100以内的偶数。不可以还让已经start()的线程去执行。会报IllegalThreadStateException

// t1.start();
//我们需要重新创建一个线程的对象,再用该对象调用start方法
MyThread t2 = new MyThread();
t2.start();

    //如下操作仍然是在main线程中执行的。
    for (int i = 0; i < 100; i++) {
        if(i % 2 == 0){
            System.out.println(Thread.currentThread().getName() + ":" + i + "***********main()************");
        }
    }
}

}

方式二:Runnable形式

  1. 创建一个实现了Runnable接口的类
  2. 实现类去实现Runnable中的抽象方法:run()
  3. 创建实现类的对象
  4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
  5. 通过Thread类的对象调用start()

Thread 和 Runable 创建线程的原理:https://www.bilibili.com/video/BV16J411h7Rd/?p=14&spm_id_from=pageDriver

实例:
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接口。 — JDK 5.0新增

如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?

    1. call()可以有返回值的。
    1. call()可以抛出异常,被外面的操作捕获,获取异常的信息
    1. Callable是支持泛型的

实例:
//1.创建一个实现Callable的实现类
class NumThread implements Callable{
//2.实现call方法,将此线程需要执行的操作声明在call()中
@Override
public Object call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
if(i % 2 == 0){
System.out.println(i);
sum += i;
}
}
return sum;
}
}

public class ThreadNew {
public static void main(String[] args) {
//3.创建Callable接口实现类的对象
NumThread numThread = new NumThread();
//4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
FutureTask futureTask = new FutureTask(numThread);
//5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
new Thread(futureTask).start();

    try {
        //6.获取Callable中call方法的返回值
        //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
        Object sum = futureTask.get();
        System.out.println("总和为:" + sum);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

}

方式四:使用线程池

经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大

提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

好处:

  • 1.提高响应速度(减少了创建新线程的时间)
  • 2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
  • 3.便于线程管理
  •  corePoolSize:核心池的大小
    
  •  maximumPoolSize:最大线程数
    
  •  keepAliveTime:线程没有任务时最多保持多长时间后会终止
    

实例:

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 != 0){
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}

}

public class ThreadPool {

public static void main(String[] args) {
    //1. 提供指定线程数量的线程池
    ExecutorService service = Executors.newFixedThreadPool(10); //多态的形式
    ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
    //设置线程池的属性

// System.out.println(service.getClass());
// service1.setCorePoolSize(15);
// service1.setKeepAliveTime();

    //2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
    service.execute(new NumberThread());//适合适用于Runnable
    service.execute(new NumberThread1());//execute方法适合适用于Runnable

// service.submit(Callable callable);//submit方法适合使用于Callable
//3.关闭连接池
service.shutdown();
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值