javase加强--多线程

多线程

线程其实是程序中的一条执行路径。

线程的创建

方法一(常用)

1.定义一个子类继承Thread类,并重写run方法
2.创建Thread的子类对象
3.调用start方法启动线程(启动线程后,会自动执行run方法中的代码)

//继承Thread
public class MyThread extends Thread{
    // 2、必须重写Thread类的run方法
    @Override
    public void run() {}

// 3、创建MyThread线程类的对象代表一个线程
        Thread t = new MyThread();
        // 4、启动线程(自动执行run方法的)
        t.start(); 

方法二

1.先写一个Runnable接口的实现类,重写run方法(这里面就是线程要执行的代码)
2.再创建一个Runnable实现类的对象
3.创建一个Thread对象,把Runnable实现类的对象传递给Thread
4.调用Thread对象的start()方法启动线程(启动后会自动执行Runnable里面的run方法) 

public class MyRunnable implements Runnable{
    // 2、重写runnable的run方法
    @Override
    public void run() {}

 // 3、创建任务对象。
        Runnable target = new MyRunnable();
        // 4、把任务对象交给一个线程对象处理。
        //  public Thread(Runnable target)
        new Thread(target).start();


//简写
        new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("子线程3输出:" + i);
                }
        }).start();

 方法三

由于前面两个都没有返回值

DK5提供了Callable接口和FutureTask类来创建线程,它最大的优点就是有返回值。

在Callable接口中有一个call方法,重写call方法就是线程要执行的代码,它是有返回值的

1.先定义一个Callable接口的实现类,重写call方法
2.创建Callable实现类的对象
3.创建FutureTask类的对象,将Callable对象传递给FutureTask
4.创建Thread对象,将Future对象传递给Thread
5.调用Thread的start()方法启动线程(启动后会自动执行call方法)
   等call()方法执行完之后,会自动将返回值结果封装到FutrueTask对象中
6.调用FutrueTask对的get()方法获取返回结果

 // 3、创建一个Callable的对象
        Callable<String> call = new MyCallable(100);
        // 4、把Callable的对象封装成一个FutureTask对象(任务对象)
        // 未来任务对象的作用?
        // 1、是一个任务对象,实现了Runnable对象.
        // 2、可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕后的结果。
        FutureTask<String> f1  = new FutureTask<>(call);
        // 5、把任务对象交给一个Thread对象
        new Thread(f1).start()

 // 6、获取线程执行完毕后返回的结果。
        // 注意:如果执行到这儿,假如上面的线程还没有执行完毕
        // 这里的代码会暂停,等待上面线程执行完毕后才会获取结果。
        String rs = f1.get();
        System.out.println(rs);

线程的方法

public class MyThread extends Thread{
    public MyThread(String name){
        super(name); //1.执行父类Thread(String name)构造器,为当前线程设置名字了
    }

//2. 哪个线程执行它,它就会得到哪个线程对象。
Thread t = Thread.currentThread();

//3. 获取线程名称
t.getName()

//4. join方法作用:让当前调用这个方法的线程先执行完。
Thread t1 = new MyThread("线程");
   t1.start();
   t1.join();

 安全问题  

多个线程同时操作同一个共享资源的时候,可能会出现业务安全问题。    

意思是每次只允许一个线程加锁,加锁后才能进入访问,访问完毕后自动释放锁,然后其他线程才能再加锁进来。  

解决这个问题使用加锁

Java提供了三种方案

1.同步代码块
2.同步方法
3.Lock锁

Lock锁

学习一下最常用的一种方式

1.首先在成员变量位子,需要创建一个Lock接口的实现类对象(这个对象就是锁对象)
    private final Lock lk = new ReentrantLock();
2.在需要上锁的地方加入下面的代码
     lk.lock(); // 加锁
     //...中间是被锁住的代码...
     lk.unlock(); // 解锁

线程池

线程池就是一个可以复用线程的技术它可以提高线程的利用率。

创建线程池

代表线程池的接口ExecutorService,而这个接口下有一个实现类叫ThreadPoolExecutor类,使用ThreadPoolExecutor类就可以用来创建线程池对象。

ExecutorService pool = new ThreadPoolExecutor(
    3,	//核心线程数有3个
    5,  //最大线程数有5个。   临时线程数=最大线程数-核心线程数=5-3=2
    8,	//临时线程存活的时间8秒。 意思是临时线程8秒没有任务执行,就会被销毁掉。
    TimeUnit.SECONDS,//时间单位(秒)
    new ArrayBlockingQueue<>(4), //任务阻塞队列,没有来得及执行的任务在,任务队列中等待
    Executors.defaultThreadFactory(), //用于创建线程的工厂对象
    new ThreadPoolExecutor.CallerRunsPolicy() //拒绝策略
);

执行任务

线程池执行的任务可以有两种,一种是Runnable任务;一种是callable任务。

Runnable
Runnable target = new MyRunnable();
pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
//下面4个任务在任务队列里排队
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);

//下面2个任务,会被临时线程的创建时机了
pool.execute(target);
pool.execute(target);
// 到了新任务的拒绝时机了!
pool.execute(target);
Callable

callable任务相对于Runnable任务来说,就是多了一个返回值。

// 2、使用线程处理Callable任务。
        Future<String> f1 = pool.submit(new MyCallable(100));
        Future<String> f2 = pool.submit(new MyCallable(200));

线程池工具类(Executors)

Java为开发者提供了一个创建线程池的工具类,叫做Executors,它提供了方法可以创建各种不能特点的线程池

// 1、通过Executors创建一个线程池对象。
        ExecutorService pool = Executors.newFixedThreadPool(17);
        // 老师:核心线程数量到底配置多少呢???
        // 计算密集型的任务:核心线程数量 = CPU的核数 + 1
        // IO密集型的任务:核心线程数量 = CPU核数 * 2

        // 2、使用线程处理Callable任务。
        Future<String> f1 = pool.submit(new MyCallable(100));

下一篇

javase加强--网络编程-CSDN博客

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值