Java基础-线程

目录:

1、线程基础教程

2、锁的案例:银行取现-特别版

3、死锁案例

 ====== ====== ======1、基础教程====== ===== =======

/**
 * 程序是静态的数据 进程是动态的程序 线程是进程中的一个连续的控制流 
 * 程序:Code+Data 
 * 进程:程序+CPU
 * 线程:创建+就绪+运行+阻塞+销毁
 * 
 * 2种生成线程类的方法 
 * 继承:java.lang.Thread+对象.start();
 * 实现:java.lang.Runnable+借助Thread类对象.start(); 
 * 2种方式都要重写run()
 * 
 * 常用方法 
 * sleep(long time); 
 * 主动休眠 yield(); 
 * 主动让出CPU join(); 立即进入执行状态
 * getName();setName();isAlive();currentThread();
 * 
 * 线程的优先级:1-10 默认5 10最高
 * 
 * 线程的同步 多个线程访问(操作)同一个资源,即发生了并发现象 为了确保共享资源合理有序的利用,而创建了同步机制
 * 实现同步:通过主要关键字synchronize和wait、notify等的配合 
 * wait():让当前线程对象进入等待状态
 * notify():让当前线程对象发出一个唤醒信号,让等待者醒来
 * 
 */
class Student extends Thread {
    private int score;

    @Override
    public synchronized void run() {
        try {
            System.out.println(this.getName() + "开始考试...");
            Thread.sleep(3000);
            System.out.println("考试结束,开始阅卷");
            Thread.sleep(3000);
            score = (int) (Math.random() * 101);
            System.out.println("阅卷结束,现在可以查询成绩了");
            this.notify();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public synchronized int getScore() {
        System.out.println(Thread.currentThread().getName() + "正在考试和阅卷,请稍等");
        try {
            this.wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return score;
    }
}

public class ThreadTest {

    public static void main(String[] args) {
        Student student = new Student();
        System.out.println("同学你考试能考多少分?");
        System.out.println("给我点时间,我去考试,看看");
        student.start();
        System.out.println("查询学生考试成绩:" + student.getScore());
    }

}

 ====== ====== ======1、锁的案例:银行取钱====== ===== =======

package com.j2se.d511;

/**
 * 测试同步问题
 * 
 * @author Administrator
 *
 */
public class Bank {
    public static void main(String[] args) {
        Account a1 = new Account(100, "高");
        Drawing draw1 = new Drawing(80, a1);
        Drawing draw2 = new Drawing(80, a1);
        draw1.start(); // 你取钱
        draw2.start(); // 你老婆取钱
    }

}

/*
 * 简单表示银行账户
 */
class Account {
    int money;
    String aname;

    public Account(int money, String aname) {
        super();
        this.money = money;
        this.aname = aname;
    }
}

/**
 * 模拟提款操作
 * 
 * @author Administrator
 *
 */
class Drawing extends Thread {
    int drawingNum; // 取多少钱
    Account account; // 要取钱的账户
    int expenseTotal; // 总共取的钱数

    public Drawing(int drawingNum, Account account) {
        super();
        this.drawingNum = drawingNum;
        this.account = account;
    }

    @Override
    public void run() {
        draw();
    }

    void draw() {
        synchronized (account) {
            if (account.money - drawingNum < 0) {
                return;
            }
            try {
                Thread.sleep(1000); // 判断完后阻塞。其他线程开始运行。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            account.money -= drawingNum;
            expenseTotal += drawingNum;
        }
        System.out.println(this.getName() + "--账户余额:" + account.money);

        System.out.println(this.getName() + "--总共取了:" + expenseTotal);
    }

}

============3、死锁案例============
class Lipstick {

}

class Mirror {

}

class Makeup extends Thread {
    int flag;
    String girl;
    static Lipstick lipstick = new Lipstick();
    static Mirror mirror = new Mirror();

    @Override
    public void run() {
        // TODO Auto-generated method stub
        doMakeup();
    }

    void doMakeup() {
        if (flag == 0) {
            synchronized (lipstick) {
                System.out.println(girl + "拿着口红!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (mirror) {
                    System.out.println(girl + "拿着镜子!");
                }

            }
        } else {
            synchronized (mirror) {
                System.out.println(girl + "拿着镜子!");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lipstick) {
                    System.out.println(girl + "拿着口红!");
                }
            }
        }
    }
}

class TestDeadLock {
    public static void main(String[] args) {
        Makeup m1 = new Makeup();
        m1.girl = "大丫";
        m1.flag = 0;
        Makeup m2 = new Makeup();
        m2.girl = "小丫";
        m2.flag = 1;
        m1.start();
        m2.start();
    }

    // 如何解决死锁问题:
    // 1. 往往是程序逻辑的问题。需要修改程序逻辑。
    // 2. 尽量不要同时持有两个对象锁。如修改成如下:

    void doMakeup() {
        if (flag == 0) {
            synchronized (lipstick) {
                System.out.println(girl + "拿着口红!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            synchronized (mirror) {
                System.out.println(girl + "拿着镜子!");
            }
        } else {
            synchronized (mirror) {
                System.out.println(girl + "拿着镜子!");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (lipstick) {
                System.out.println(girl + "拿着口红!");
            }
        }
    }

}

/*
 * 同步是一种解决问题的思路,结合前面卫生间的示例,互斥方式解决多线程的原理是, 当一个人进入到卫生间内部时,别的人只能在外部时刻等待,
 * 这样就相当于别的人虽然没有事情做,但是还是要占用别的人的时间, 浪费系统的执行资源。而同步解决问题的原理是,如果一个人进入到卫生间内部时,
 * 则别的人可以去睡觉,不占用系统资源,而当这个人从卫生间出来以后, 把这个睡觉的人叫醒[就是wait,notify的应用。],则它就可以使用临界资源了。
 * 所以使用同步的思路解决多线程问题更 加有效,更加节约系统的资源。
 */
原文地址:https://www.cnblogs.com/qixiawentang/p/5483305.html