Java线程的创建

Java线程的创建

方式一:

1.创建一个继承于Thread类的子类

2.重写Thread类的run()

3.创建Thread类的子类对象

4.通过此对象调用start()

public class ThreadTest {
    public static void main(String[] args) {
        //创建Thread类的子类的对象
        MyThread mt = new MyThread();
        //调用此对象的start():1.启动当前线程;2.调用当前线程的run();3.start()方法在一个对象中只能调用一次
        mt.start();

        //重复使用线程中的方法,不能重复调用一个对象中的start,只能重新new一个对象,起用线程
        MyThread mt1 = new MyThread();
        mt1.start();

        //不能直接调用run()方法启动线程
        //mt.run()//还是在主线程中执行

        //两个线程,以下代码仍然再main()中执行
        System.out.println("Hello World");//先输出Hello World,再执行mt.start()

        //创建Thread类的匿名子类的方式(只用一次)
        new Thread(){
            @Override
            public void run(){
                for (int i = 0; i <100 ; i++) {
                    if(i % 2 != 0){
                        System.out.println(i);
                    }

                }
            }
        }.start();
    }

}

class MyThread extends Thread{
    @Override
    public void run(){
        for (int i = 0; i < 100; i++){
            if(i%2 == 0){
                System.out.println(i);
            }
        }
    }
}
方式二:实现Runnable接口

1.创建一个实现了Runnable接口的类

2.实现类去实现Runnable中的抽象方法:run()

3.创建实现类的对象

4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象

5.通过Thread类的对象调用start()

public class ThreadTest {
    public static void main(String[] args) {
        //3.创建实现类的对象
        MThread mt1 = new MThread();
        //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
        Thread t1 = new Thread(mt1);
        //5.通过Thread类的对象调用start():1.启动线程;2.调用当前线程的run()-->调用了Runnable类型的target的run(),即mt1的run()
        t1.start();

        //再启动一个线程,遍历100以内的偶数
        Thread t2 = new Thread(mt1);
        t2.start();

    }

}

class MThread implements Runnable{
    @Override
    public void run(){
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0){
                System.out.println(Thread.currentThread().getName()+ ":" + i);
            }

        }
    }
}
开发中一般优先选择第二种实现Runnable接口的方式。

1.实现的方式没有类的继承性的局限性;

2.实现的方式更适合处理多个线程有共享数据的情况。

方式三:实现Callable接口

Java 5.0 在 java.util.concurrent 提供了一个新的创建执行线程的方式: 实现 Callable 接口。

Callable 接口类似于 Runnable,但是 Runnable 不会返回结果,并且无法抛出经过检查的异常,而 Callable 依赖 FutureTask 类获取返回结果。

步骤:

1.创建一个实现Callable的实现类;

2.实现call方法,将线程需要做的操作声明在call方法中;

3.需要创建Callable接口实现类的对象;

4.将此Callable接口实现类的对象作为参数传递到FutureTask的创建对象中;

5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象并start();

6.可选择性获取Callable方法中的返回值。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author zane
 * @create 2023-01-06-14:50
 *
 * 创建线程的方式三:实现Callable接口 jdk5.0新增
 *
 * 1.创建一个实现Callable的实现类
 * 2.实现call方法,将线程需要做的操作声明在call方法中
 * 3.需要创建Callable接口实现类的对象
 * 4.将此Callable接口实现类的对象作为参数传递到FutureTask的创建对象中
 * 5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象并start()
 * 6.可选择性获取Callable方法中的返回值
 *
 * Callable和Runnable接口对比
 * 1.call()有返回值
 * 2.call()可以抛出异常
 * 3.Callable支持泛型
 */
public class ThreadNewtest {
    public static void main(String[] args) {
        NumThread numthread = new NumThread();
        FutureTask futuretask = new FutureTask(numthread);
        new Thread(futuretask).start();

        try{
            //get方法的返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值
            Object sum = futuretask.get();
            System.out.println("Total sum is: " + sum);

        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (ExecutionException e){
            e.printStackTrace();
        }
    }

}

class NumThread implements Callable{

    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            if (i % 2 == 0){
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}
Callable和Runnable接口对比

1.call()有返回值

2.call()可以抛出异常

3.Callable支持泛型

方式四:线程池创建

JAVA中使用ThreadPoolExecutor来创建线程池。

步骤:

1.提供指定的数量的线程池

2.执行指定的线程的操作,需提供实现Runnable或Callable接口实现类的对象

3.关闭连接池

优势:

1.提高响应速度,减少了线程创建的时间

2.降低了资源消耗,重复利用线程池中的线程

3.便于对线程进行管理:

​ corePoolSize:核心池的大小

​ maximumPoolSize:最大线程数

​ keepAliveTime:线程没有任务时最多保持的时间

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author zane
 * @create 2023-01-05-16:37
 * 线程创建方式四:线程池创建
 * 1.提供指定的数量的线程池
 * 2.执行指定的线程的操作,需提供实现Runnable或Callable接口实现类的对象
 * 3.关闭连接池
 *
 * 优势:
 * 1.提高响应速度,减少了线程创建的时间
 * 2.降低了资源消耗,重复利用线程池中的线程
 * 3.便于对线程进行管理:
 *  corePoolSize:核心池的大小
 *  maximumPoolSize:最大线程数
 *  keepAliveTime:线程没有任务时最多保持的时间
 *
 */
public class ConcurrentTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        //executor类别:executor.getClass()
        ThreadPoolExecutor executor1 = (ThreadPoolExecutor) executor;
        //设置线程池属性
        executor1.setCorePoolSize(3);

//        executor1.setKeepAliveTime(200);

//        Semaphore semaphore = new Semaphore(3);//配置只能发布3个运行许可证
        for (int i = 0; i < 3; i++) {
            executor1.execute(new Con());//仅创建,没有实现线程同步
        }


            //execute适用于Runnable
            //executor.execute(new Con());
            //submit适合用Callable
//            executor.submit(new Con());


        executor1.shutdown();
    }

}

class Con implements Runnable{
    private static int ticket = 100;

	//还未解决线程池同步的问题
    
    @Override
    public void run(){
        try {
            Thread.currentThread().sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while(true) {
            if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ": Tickets are selling,ticket id: " + ticket);
                    ticket--;
                } else {
                    System.out.println("Tickets were sold out.");
                    break;
                }
        }
    }
}

通过Executors.newFixedThreadPool()来创建线程池,会存在一个无界队列,将未操作的任务放入其中,随着队列中任务的增加,可能会爆内存。详细可以参考这篇blog:https://blog.csdn.net/qq_40096897/article/details/121660747

因此一些公司会限制该方法创建线程池,并且,阿里Java开发手册中强制规定,通过ThreadPollExecutor的方式创建线程池。
在这里插入图片描述

public static ExecutorService newThreadPool(int threadNum){
        return new java.util.concurrent.ThreadPoolExecutor(threadNum,threadNum,
                0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值