线程安全&&定时器总结

发布时间 2023-12-28 20:48:43作者: ZWJAS

总结

线程

线程:执行的独立代码
线程执行是靠cpu分配时间片,同一个时间片上只能执行一个线程
线程的状态:

  1. 新建
  2. 就绪
  3. 运行
  4. 阻塞
  5. 死亡

Thread:多线程的类

  1. currentThread()
  2. getName() ,setName()
  3. sleep()

实现多线程的方式
1. 继承Thread,重写run
2. 实现Runnable,重写run

实现线程安全的三种方式

线程的执行是靠cpu分配时间片
存在一票多卖:多个线程同时访问一个数据,同一个数据被访问多次,存在线程安全问题
线程安全问题是怎样发生:线程要执行的代码还没有全部执行完,另一个线程有开是执行
怎样来解决这个线程安全问题:保证线程要执行的代码全部要执行完毕

synchronized (参数:引用类型,所有的线程对象都能共享的(static修饰,字节码对象) )

  1. 同步代码块:将同步代码快作为一个整体

    继承Thread,重写run

    public class Tickets extends Thread{
        private static int count = 1;
    
        public Tickets() {
        }
    
        public Tickets(String name) {
            super(name);
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 30; i++) {
                synchronized (this.getClass()) {
                    if(count <= 30) {
                        // 获取当前线程的名
                        String name = Thread.currentThread().getName();
                        System.out.println(name + "窗口:卖出第" + count + "张票");
                        count++;
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
    }
    
    // 测试类
    public class TicketsTest {
        public static void main(String[] args) {
            Tickets t1 = new Tickets("花泽");
            Tickets t2 = new Tickets("龙泽");
            Tickets t3 = new Tickets("波多野蘋蘋");
            t3.setPriority(Thread.MAX_PRIORITY);
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

    实现Runnable,重写run

    public class Tickets implements Runnable {
        private int count = 1; // 可以是实例变量,也可以是类变量
        private ReentrantLock lock = new ReentrantLock(true);
    
        // 使用同步代码块来处理线程不安全的问题
        public void run() {
            for (int i = 0; i < 30; i++) {
                synchronized (this.getClass()) { // this:当前对象
                    if (count <= 30) {
                        String name = Thread.currentThread().getName(); // 获取当前线程的名字
                        System.out.println(name + "窗口:卖出第" + count + "张票");
                        count++;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
    
    // 测试类
    public class TicketsTest {
        public static void main(String[] args) {
            // 1、创建Runnable对象
            Tickets tickets = new Tickets();
            // 2、创建线程
            Thread t1 = new Thread(tickets, "蘋蘋1号");
            Thread t2 = new Thread(tickets, "蘋蘋2号");
            Thread t3 = new Thread(tickets, "蘋蘋3号");
            // 3、启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
  2. 同步方法:用synchronized 修饰方法

    继承Thread,重写run

    public class Tickets2 extends Thread{
        private static int count = 1;
    
        public Tickets2() {
        }
    
        public Tickets2(String name) {
            super(name);
        }
    
        // 设计一个买票的方法
        public static synchronized void sale() { // 这个就是同步方法,同步实例方法的锁默认是this,同步类方法的锁是当前类的字节码对象
                if (count <= 30) {
                    // 获取当前线程的名
                    String name = Thread.currentThread().getName();
                    System.out.println(name + "窗口:卖出第" + count + "张票");
                    count++;
                }
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 30; i++) {
                sale();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    
    public class Tickets2Test {
        public static void main(String[] args) {
            Tickets2 t1 = new Tickets2("花泽");
            Tickets2 t2 = new Tickets2("龙泽");
            Tickets2 t3 = new Tickets2("波多野蘋蘋");
            t3.setPriority(Thread.MAX_PRIORITY);
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

    实现Runnable,重写run

    public class Tickets implements Runnable {
        private int count = 1; // 可以是实例变量,也可以是类变量
        private ReentrantLock lock = new ReentrantLock(true);
    
        // 使用同步方法
        public synchronized void sale() {
            if (count <= 30) {
                String name = Thread.currentThread().getName(); // 获取当前线程的名字
                System.out.println(name + "窗口:卖出第" + count + "张票");
                count++;
            }
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 30; i++) {
                sale();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    
    // 测试类
    public class TicketsTest {
        public static void main(String[] args) {
            // 1、创建Runnable对象
            Tickets tickets = new Tickets();
            // 2、创建线程
            Thread t1 = new Thread(tickets, "蘋蘋1号");
            Thread t2 = new Thread(tickets, "蘋蘋2号");
            Thread t3 = new Thread(tickets, "蘋蘋3号");
            // 3、启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
  3. 同步锁:ReentrantLock,lock():上锁,unlock():解锁

    继承Thread,重写run

    public class Tickets3 extends Thread{
        // 创建同步锁
        private  static ReentrantLock lock = new ReentrantLock(true); // 不带公平机制
        private static int count = 1;
    
        public Tickets3() {
        }
    
        public Tickets3(String name) {
            super(name);
        }
    
    
        @Override
        public void run() {
            // 使用同步锁
            for (int i = 0; i < 30; i++) {
                    // 上锁
                    lock.lock();
                    try {
                        if (count <= 30) {
                            // 获取当前线程的名
                            String name = Thread.currentThread().getName();
                            System.out.println(name + "窗口:卖出第" + count + "张票");
                            count++;
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }finally {
                        // 释放锁
                        lock.unlock();
                    }
            }
        }
    }
    
    public class Tickets3Test {
        public static void main(String[] args) {
            Tickets3 t1 = new Tickets3("花泽");
            Tickets3 t2 = new Tickets3("龙泽");
            Tickets3 t3 = new Tickets3("波多野蘋蘋");
            t3.setPriority(Thread.MAX_PRIORITY);
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

    实现Runnable,重写run

    public class Tickets implements Runnable {
        private int count = 1; // 可以是实例变量,也可以是类变量
        private ReentrantLock lock = new ReentrantLock(true);
    
        // 使用同步锁
        @Override
        public void run() {
            for (int i = 0; i < 30; i++) {
                // 上锁
                lock.lock();
                try {
                    if (count <= 30) {
                        String name = Thread.currentThread().getName(); // 获取当前线程的名字
                        System.out.println(name + "窗口:卖出第" + count + "张票");
                        count++;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }finally {
                    // 解锁
                    lock.unlock();
                }
            }
    
        }
    }
    
    // 测试类
    public class TicketsTest {
        public static void main(String[] args) {
            // 1、创建Runnable对象
            Tickets tickets = new Tickets();
            // 2、创建线程
            Thread t1 = new Thread(tickets, "蘋蘋1号");
            Thread t2 = new Thread(tickets, "蘋蘋2号");
            Thread t3 = new Thread(tickets, "蘋蘋3号");
            // 3、启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

Timer:定时器(也可作为守护线程)

定时器:在指定时间做指定事情,比如:闹钟

在开发定时器的作用:1、定时发邮件 2、定时备份 3、定时写日志

就是学习一个类:Timer:定时器类,做定时任务的

TimerTask:定时任务,另外一个线程

// 定时任务
import java.util.TimerTask;

/**
 * 写一个定时任务
 */
public class SayHi extends TimerTask {
    @Override
    public void run() {
        System.out.println("hello boys and girls......");
    }
}
// 测试类
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

public class TimerDemo {
    public static void main(String[] args) {
        // 创建一个定时器
        Timer timer = new Timer(); // 创建了一个线程
        // 调用其他线程:schedule()
        SayHi sayHi = new SayHi();
//        timer.schedule(sayHi,2000); // 2秒后执行定时任务,一次性任务
//        timer.schedule(sayHi,2000,3000); // 周期性的任务
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.SECOND, -10);
        Date date = cal.getTime();
//        timer.schedule(sayHi,date,3000);

        timer.scheduleAtFixedRate(sayHi,date,3000);
    }
}