什么是线程?如何使用线程?

什么是线程?

编辑搜图

如图,我们先介绍一下进程,进程只电脑里执行的每个软件,例如QQ\微信等程序都统一称之为进程,因为线程是在进程里执行的,一个进程里有多个线程。

进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。

创建线程的三种方式

public class ThreadDemo {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();

        new MyThread().start();//简化写法
        


        MyThread2 myThread2 = new MyThread2();
        new Thread(myThread2).start();

        new Thread(new MyThread2()).start();//简化写法



        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread3());//加个泛型约束Integer
        new Thread(futureTask).start();
    }


}

//继承 Thread 类
//Thread.currentThread().getName()获取当前线程的名字
class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"我是第一种方式");
    }
}
//实现 Runnable 接口
class MyThread2 implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"我是第二种方式");
    }
}
//实现 Callable 接口
class MyThread3 implements Callable {

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"我是第三种方式");
        return 666;
    }
}

运行结果:

线程本身是不安全的

通过代码实现线程不安全的情况:例如火车站买票,20张票3个人一起买

public class Ticket {
    public static void main(String[] args) {
        MyTicket myTicket = new MyTicket();

        new Thread(myTicket,"小明").start();

        new Thread(myTicket,"小红").start();

        new Thread(myTicket,"小亮").start();
    }
}
//定义一个内部类
class MyTicket implements Runnable {
    private int ticket = 20; //设置票数 20张票
    boolean flag =true; //默认为true
    @Override
    public void run() {
        while(flag){
            try {
                stop();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //定义一个方法 停止抢票
    public void stop() throws InterruptedException {
        if (ticket<=0){
            flag = false;//如果票数为0或小于0 停止抢票
            return;
        }
        //为了实现不安全的结果 让线程等待
        Thread.sleep(100);
        System.out.println(Thread.currentThread().getName()+"买到了第"+ticket-- +"张票");
    }
}

编辑搜图

运行结果:小红和小亮都抢到了第10张票。这个在实际中肯定是不允许的

如何确保线程安全?

  1. synchronized

  2. Lock

synchronized关键字,就是用来控制线程同步的,保证我们的线程在多线程环境下,不被多个线程同时执行,确保我们数据的完整性,使用方法一般是加在方法上。

//定义一个内部类
class MyTicket implements Runnable {
    private int ticket = 20; //设置票数 20张票
    boolean flag =true; //默认为true
    @Override
    public synchronized void run() {
        while(flag){
            try {
                stop();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

编辑搜图

这样就可以确保我们的线程同步了,同时这里需要注意一个大家平时忽略的问题,首先synchronized锁的是括号里的对象,而不是代码,其次,对于非静态的synchronized方法,锁的是对象本身也就是this。

当synchronized锁住一个对象之后,别的线程如果想要获取锁对象,那么就必须等这个线程执行完释放锁对象之后才可以,否则一直处于等待状态。

注意点:虽然加synchronized关键字,可以让我们的线程变得安全,但是我们在用的时候,也要注意缩小synchronized的使用范围,如果随意使用时很影响程序的性能,别的对象想拿到锁,结果你没用锁还一直把锁占用,这样就有点浪费资源。

Lock的用法如下图:

public class LockTest {
    public static void main(String[] args) {
        MyLock myLock =new MyLock();
        new Thread(myLock,"小明").start();
        new Thread(myLock,"小红").start();
        new Thread(myLock,"小亮").start();
    }
}
class MyLock implements Runnable{
    int piaoNum = 10;
    boolean flag =true;
    private final ReentrantLock lock = new ReentrantLock(); //定义一个锁
    @Override
    public void run() {
        while(flag) {
            lock.lock();//锁
            if (piaoNum > 0) {
                try {
                    Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName() + "购买了第" + piaoNum-- + "张票");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();//释放锁!!!
                }

            } else {
                flag = false;
            }
        }
    }
}

编辑搜图

注意一定要在finally中释放锁
以上就是使用Lock,来保证我们线程安全的方式
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值