Java中的线程处理

本文介绍了Java中的线程概念、进程与守护进程的区别、线程的实现方式(继承Thread、实现Runnable和Callable接口)、线程安全(同步代码块和同步方法)、以及线程池的创建(静态和非静态方法)。
摘要由CSDN通过智能技术生成

1 线程的概念

1.1 线程与进程

这部分内容其实是属于《操作系统》这门课程的,接下来将详细的请看大佬的博客
操作系统常见面试题总结(上)

  1. 守护进程:备胎进程,就是当非守护进程执行完毕之后,守护进程会逐渐关闭,即还没有将任务完全执行完毕,也会提前关闭,当时守护进程不会立即关闭。

1.2 线程的实现

1.3 线程池

核心线程:线程池中最大线程数
队伍长度:排队等待的线程数量
临时线程:队伍排满后,才会创建临时线程

2 代码实践

2.1 继承 Thread 类

package cn.edu.njust.threaddemo;

public class MyThread extends Thread{
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + ": 测试" + i);
        }
    }
}

package cn.edu.njust.threaddemo;


/**
 * 第一种实现方式:继承Thread类别
 */
public class ThreadDemo01 {
    public static void main(String[] args) {
        // 创建线程
        MyThread mt1 = new MyThread();
        // 给线程指定名字
        mt1.setName("线程1");
        // 调用start()方法,开启线程
        mt1.start();

        // 创建第二个线程
        MyThread mt2 = new MyThread();
        // 指定名称
        mt2.setName("线程2");
        // 调用start()方法启动线程
        mt2.start();
    }
}

2.2 实现 Runnable 接口

package cn.edu.njust.threaddemo;

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            // 在这种实现方式中吗,不能直接调用getName()方法,需要先获取当前执行的线程
            System.out.println(Thread.currentThread().getName() + ":测试" + i);
        }
    }
}

package cn.edu.njust.threaddemo;

/**
 * 创建多线程的方式2:实现 Runnable 接口
 */
public class RunnableDemo01 {
    public static void main(String[] args) {
        // 创建任务对象
        MyRunnable mr = new MyRunnable();
        // 将任务交给线程
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);

        // 为线程设置名字,方便观察输出效果
        t1.setName("线程1");
        t2.setName("线程2");

        // 启动线程,执行任务
        t1.start();
        t2.start();

    }
}

2.3 实现 Callable 接口

package cn.edu.njust.threaddemo;

import java.util.concurrent.Callable;

public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
        // 这个方法是有返回值的
        int res = 0;
        for (int i = 0; i < 10; i++) {
            res += i;
        }
        return res;
    }
}

package cn.edu.njust.threaddemo;

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

public class CallableDemo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 创建任务对象
        MyCallable mc1 = new MyCallable();
        // 创建 FutureTask 对象(用于管理多线程的运行结果)
        FutureTask<Integer> futureTask = new FutureTask<>(mc1);
        // 创建线程,用于执行任务
        Thread t1 = new Thread(futureTask);
        // 启动线程
        t1.start();

        // 获取结果
        Integer ans = futureTask.get();
        System.out.println("线程运行结果:" + ans);

    }
}

2.4 线程安全

2.4.1 同步代码块

package cn.edu.njust.threadsafe;

/**
 * 研究同步代码块的锁操作
 */
public class MyThread01 extends Thread {
    private static int tickets = 0;

    // 声明一个对象,用于给 synchronized 同步
    private static final Object obj = new Object();
    @Override
    public void run() {
        /*
        不能这样写,这样写在多线程情况下会使得tickets数量超过100
        因为这样写锁住的只是循环内部的东西

        while (tickets < 100) {
            //
            synchronized (obj) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                tickets ++;
                System.out.println(getName() + "已购买第" + tickets + "张票");
            }
        }*/

        while (true) {
            /*
            * 这里可以使用 synchronized (obj),因为在成员变量中它被声明为了唯一的产量
            * 当时真是开发中不会这样
            * 一般都是对象所或者类锁,如下,直接获取.class对象,一定是唯一的
            * */
            // synchronized (obj) {
            synchronized (Thread.class) {
                if(tickets >= 100) break;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                tickets ++;
                System.out.println(getName() + "已购买第" + tickets + "张票");
            }
        }
    }
}

package cn.edu.njust.threadsafe;

public class ThreadTestDemo01 {
    public static void main(String[] args) {
        // 构造线程
        MyThread01 mt1 = new MyThread01();
        MyThread01 mt2 = new MyThread01();
        MyThread01 mt3 = new MyThread01();
        // 设置线程的名称
        mt1.setName("客户1");
        mt2.setName("客户2");
        mt3.setName("客户3");
        // 启动各个线程执行任务
        mt1.start();
        mt2.start();
        mt3.start();

    }
}

2.4.2 同步方法

package cn.edu.njust.threadsafe;

/**
 * 同步方法
 */
public class MyRunnable implements Runnable {
    private int tickets = 0;

    @Override
    public void run() {
        while (true) {
            if (!buyTickets()) break;
        }
    }

    /**
     * 这里锁的是 this,即谁调用,就锁住谁
     * @return
     */
    private synchronized boolean buyTickets() {
        if (tickets >= 100) {
            return false;
        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        tickets++;
        System.out.println(Thread.currentThread().getName() + "购买了第" + tickets + "张票");

        return true;
    }
}

package cn.edu.njust.threadsafe;

public class ThreadTestDemo02 {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();

        Thread t1 = new Thread(mr, "客户1");
        Thread t2 = new Thread(mr, "客户2");
        Thread t3 = new Thread(mr, "客户3");

        t1.start();
        t2.start();
        t3.start();

    }
}

2.5 线程池

2.5.1 静态方法创建

package cn.edu.njust.threaddemo;

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

/**
 * 线程池的基本创建
 */
public class ThreadPoolDemo01 {
    public static void main(String[] args) {
        // 创建没有上限的线程池,实际上是上线是int类型的最大值,但是实际计算机支持不了这么多
        ExecutorService pool1 = Executors.newCachedThreadPool();
        // 创建指定容量的现称池
        ExecutorService pool2 = Executors.newFixedThreadPool(3);

        // 提交任务,将线程任务交给线程池
        /*pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());*/

        pool2.submit(new MyRunnable());
        pool2.submit(new MyRunnable());
        pool2.submit(new MyRunnable());
        pool2.submit(new MyRunnable());
        pool2.submit(new MyRunnable());

        // 销毁线程池
        pool1.shutdown();
        pool2.shutdown();
    }
}

2.5.2 非静态方法

3 常用方法汇总

3.1 构造器

** 方法原型**说明
public Thread()无参构造
public Thread(String name)指定名字
public Thread(Runnable target)指定任务
public Thread(Runnable target, String name)可以在同时设置任务和设置名字

3.2 常用方法

** 方法原型**说明
public final synchronized void setName(String name)为线程设置名字
public final String getName()获取线程的名字
public static native Thread currentThread()获取到当前正在执行的线程
public static native void sleep(long millis) throws InterruptedException使当前进程休眠一定的时间,时间结束后自动苏醒
public final void setPriority(int newPriority)设置优先级
public final int getPriority()或许线程的优先级
public final void setDaemon(boolean on)将一个线程设置为守护进程
public static native void yield()出让线程
public final void join() throws InterruptedException将一个线程插入到当前线程之前,插入的线程执行完毕之后再执行当前线程

3.3 线程池相关方法

**方法原型 **说明
public static ExecutorService newCachedThreadPool()创建一个上限是 int 类型最大值的线程池
public static ExecutorService newFixedThreadPool(int nThreads)创建指定容量的线程池
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拜见老天師

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值