线程的方法与线程锁

1、线程的五个状态

新建(NEW): 新创建了一个线程对象
可运行(RUNNABLE): 调用了start方法,线程就处于可执行状态。
运行(RUNNING): 可执行的线程对象获得cpu的时间片,被cpu调度执行。
阻塞(BLOCKED): 线程由于某种原因放弃了cpu的使用权,暂时停止运行。
死亡(DEAD): 线程运行完毕或者因为异常退出了run方法,停止了运行。
线程的方法与线程锁
注意: 阻塞状态不能变为可执行状态,只能恢复可执行状态重新等待cpu调配

2、线程的常用方法

1、yeild方法(礼让)

public class MethodVip implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"在运行。。。");
    }

    public static void main(String[] args) {
        Method method = new Method();
        MethodVip methodVip = new MethodVip();

        new Thread(methodVip, "佩奇").start();
        new Thread(method,"乔治").start();
    }
}

class Method implements Runnable{

    @Override
    public void run() {
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"在运行。。。");

    }
}

分别让两个不同的类实现Runable接口,然后重写run方法,在其中一个run方法内使用yeild方法,然后调用两个线程的start方法,开启两个线程。运行多次发现使用yeild方法的线程一般都会后执行,但也有先执行的时候,由此可见礼让并不一定成功,cpu调度器可以不理会线程的礼让请求。

2、join方法(插队)

public class MethodVip implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName()+"在运行。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MethodVip methodVip = new MethodVip();

        Thread p1 = new Thread(methodVip, "佩奇");

        p1.start();
        p1.join();

        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"在运行。。。");
        }

    }
}

使用join方法的线程会使主线程阻塞,自己执行完毕,主线程才能执行。
3、sleep方法(睡眠)和wait方法
sleep方法会让线程休眠,wait方法会让线程等待。区别是sleep方法不会释放锁,而wait方法会释放锁,wait是Object类的方法,sleep是Thead类的方法。

3、线程锁

1、synchronized

public class SynchronizeTest {

    public static void main(String[] args) {
        Bank bank = new Bank("建设银行", 100);
        Person boy = new Person(bank, 50, "boy");
        Person girl = new Person(bank, 80, "girl");

        boy.start();
        girl.start();
    }
}

class Bank {
    private String name;
    public int money;

    public Bank(String name,int money) {
        this.name = name;
        this.money = money;
    }
}

class Person extends Thread{
    Bank bank;
    private int myMonmey;
    private int takeMoney;

    public Person(Bank bank,int takeMoney,String name){
        super(name);
        this.bank=bank;
        this.takeMoney=takeMoney;

    }
    @Override
    public void run() {
        synchronized (bank){
            if (bank.money-takeMoney<=0){
                System.out.println(Thread.currentThread().getName()+"的账户没钱了");
                return;
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            myMonmey=myMonmey+takeMoney;
            System.out.println(this.getName()+"取了"+myMonmey);

            bank.money=bank.money-takeMoney;
            System.out.println("银行的钱还剩"+bank.money);
        }
    }
}

这是模拟两个人同时在银行里面取钱的操作,由于有sleep模拟了延时,所以会出现两个人同时进入银行取钱,看到100块钱,可以对这100块钱进行操作,操作完后退出,可能出现负值。理论上资源只有一份,这样会默认资源有两份。因此我们必须对资源上锁。synchronized默认锁的是this对象,我们使用同步代码块,锁住bank对象,这样银行里的钱就只有等一个人操作完之后,另一个人才能操作。
2、lock

import java.util.concurrent.locks.ReentrantLock;

public class LockTest1{

    public static void main(String[] args) {
        Lock2 lock2 = new Lock2();
        new Thread(lock2,"黄牛").start();
        new Thread(lock2,"学生").start();
        new Thread(lock2,"老师").start();
    }
}

class Lock2 implements Runnable{

    private int ticket=10;
    boolean flag = true;
    ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while(ticket>2){
            try{
                lock.lock();
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"买到了第张" + ticket--+"票");

            }finally {
                lock.unlock();
            }
        }
    }
}

Lock是显示锁,需要用lock方法上锁再用unlock方法解锁,synchronized 锁是隐式锁,不需要声明。

上一篇:PAT 1012 The Best Rank


下一篇:JAVA---设计模式