简单了解一下多线程

线程安全问题

经典的买票案例:

public class TicketNum implements Runnable {
    int tickNum=100;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            if(tickNum>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"还有"+(tickNum--)+"张票");
            }
        }
    }
}

public class ThreadDemo {
    public static void main(String[] args) {
        TicketNum tn=new TicketNum();
        Thread t1=new Thread(tn,"窗口一");
        Thread t2=new Thread(tn,"窗口二");
        Thread t3=new Thread(tn,"窗口三");

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

结果
这里写图片描述
这就是线程安全问题,产生原因:
A:是否是多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据

解决

第一种:同步

public class TicketNum implements Runnable {
    int tickNum=100;
    @Override
    //方法上加synchronized 
    public synchronized void run() {
        // TODO Auto-generated method stub
        while(true){
            if(tickNum>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"还有"+(tickNum--)+"张票");
            }
        }
    }
}

public class ThreadDemo {
    public static void main(String[] args) {
        TicketNum tn=new TicketNum();
        Thread t1=new Thread(tn,"窗口一");
        Thread t2=new Thread(tn,"窗口二");
        Thread t3=new Thread(tn,"窗口三");

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

结果:
这里写图片描述

第二种:加锁lock

public class TicketNum2 implements Runnable {
    int tickNum = 100;
    private static Lock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true) {
            lock.lock();// 锁定   
            if (tickNum > 0) {
                try {
                    Thread.sleep(100);                  System.out.println(Thread.currentThread().getName() + "上锁");                    System.out.println(Thread.currentThread().getName() + "还有" + (tickNum--) + "张票");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {                 System.out.println(Thread.currentThread().getName() + "解锁");
                    lock.unlock();// 解锁
                }
            }
        }
    }
}

public class LockDemo {
public static void main(String[] args) {
    TicketNum2 tn=new TicketNum2();
    Thread t1=new Thread(tn,"窗口一");
    Thread t2=new Thread(tn,"窗口二");
    Thread t3=new Thread(tn,"窗口三"); 
    t1.start();
    t2.start();
    t3.start();
}
}

结果:
这里写图片描述

sleep()与wait()

对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。

sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。

在调用sleep()方法的过程中,线程不会释放对象锁。

而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备

获取对象锁进入运行状态。

创建线程的方式

1.继承Thread类,不推荐
2.实现Runnable 接口
3.实现java.util.concurrent下的Callable接口

猜你喜欢

转载自blog.csdn.net/bushanyantanzhe/article/details/79222288