[Java] 多线程

例1:单线程

Punishment.java

public class Punishment {
    private int leftCopyCount;
    private String wordToCopy;

    public Punishment(int i, String s) {
        this.leftCopyCount = i;
        this.wordToCopy = s;
    }

    public int getLeftCopyCount() {
        return leftCopyCount;
    }

    public void setLeftCopyCount(int leftCopyCount) {
        this.leftCopyCount = leftCopyCount;
    }

    public String getWordToCopy() {
        return wordToCopy;
    }

    public void setWordToCopy(String wordToCopy) {
        this.wordToCopy = wordToCopy;
    }
}

Student.java

public class Student {
    private String name;
    private Punishment punishment;

    public Student(String name,Punishment punishment){
        this.name = name;
        this.punishment = punishment;
    }

    public void copyWord(){
        int count = 0;
        String threadName = Thread.currentThread().getName();

        while(true){
            if(punishment.getLeftCopyCount() > 0){
                int leftCopyCount = punishment.getLeftCopyCount();
                System.out.println(threadName+"线程-" + name + "抄写" + punishment.getWordToCopy() + "。还要抄写" +
                        --leftCopyCount + "次");
                punishment.setLeftCopyCount(leftCopyCount);
                count++;
            }else{
                break;
            }
        }
        System.out.println(threadName + "线程-" + name + "一共抄写了" + count + "次!");
    }
} 

StudentClient.java

public class StudentClient {
    public static void main(String[] args) {
        Punishment punishment = new Punishment(100,"internationalization");
        Student student = new Student("小明",punishment);
        student.copyWord();
    }
}

main线程-小明抄写internationalization。还要抄写99次

...
main线程-小明抄写internationalization。还要抄写0次
main线程-小明一共抄写了100次!

例2:继承Thread实现独立线程

与例1不同处:

  • 继承Thread类
  • 调用Thread构造方法,设置threadName
  • 重写run方法,调用copyWord完成任务
  • 在main()中调用 start 方法

Student.java

public class Student extends Thread{
    private String name;
    private Punishment punishment;

    public Student(String name,Punishment punishment){
        super(name);
        this.name = name;
        this.punishment = punishment;
    }

    public void copyWord(){
        int count = 0;
        String threadName = Thread.currentThread().getName();

        while(true){
            if(punishment.getLeftCopyCount() > 0){
                int leftCopyCount = punishment.getLeftCopyCount();
                System.out.println(threadName+"线程-" + name + "抄写" + punishment.getWordToCopy() + "。还要抄写" +
                        --leftCopyCount + "次");
                punishment.setLeftCopyCount(leftCopyCount);
                count++;
            }else{
                break;
            }
        }
        System.out.println(threadName + "线程-" + name + "一共抄写了" + count + "次!");
    }
    @Override
    public void run(){
        copyWord();
    }
}

StudentClient.java

public class StudentClient {
    public static void main(String[] args) {
        Punishment punishment = new Punishment(100,"internationalization");
        Student student = new Student("小明",punishment);
        student.start();
        System.out.println("Another thread will finish the punishment。 main thread is finished" );
    }
}

Another thread will finish the punishment。 main thread is finished
小明线程-小明抄写internationalization。还要抄写99次

...

小明线程-小明抄写internationalization。还要抄写0次
小明线程-小明一共抄写了100次!

例2:继承Thread实现多线程

StudentClient.java

public class StudentClient {
    public static void main(String[] args) {
        Punishment punishment = new Punishment(100,"internationalization");
        Student xiaoming = new Student("小明",punishment);
        xiaoming.start();
        Student xiaozhang = new Student("小张",punishment);
        xiaozhang.start();
        Student xiaozhao = new Student("小赵",punishment);
        xiaozhao.start();
    }
}

小明线程-小明一共抄写了100次!

小张线程-小张一共抄写了100次!

小赵线程-小赵一共抄写了100次!

例3:继承Runnable实现多线程

Student.java

public class Student implements Runnable{
    private String name;
    private Punishment punishment;

    public Student(String name,Punishment punishment){
        this.name = name;
        this.punishment = punishment;
    }

    public void copyWord(){
        int count = 0;
        String threadName = Thread.currentThread().getName();

        while(true){
            if(punishment.getLeftCopyCount() > 0){
                int leftCopyCount = punishment.getLeftCopyCount();
                System.out.println(threadName+"线程-" + name + "抄写" + punishment.getWordToCopy() + "。还要抄写" +
                        --leftCopyCount + "次");
//              --leftCopyCount;
                punishment.setLeftCopyCount(leftCopyCount);
                count++;
            }else{
                break;
            }
        }
        System.out.println(threadName + "线程-" + name + "一共抄写了" + count + "次!");
    }
    @Override
    public void run(){
        copyWord();
    }
}  

StudentClient.java

public class StudentClient {
    public static void main(String[] args) {
        Punishment punishment = new Punishment(100,"internationalization");
        Thread xiaoming = new Thread(new Student("小明",punishment));
        xiaoming.start();
    }
}

结果同例2

例4:多线程同时抄写

  • 取得剩余次数后马上更新-1后的次数。看似是避免了读取和更新间的时间间隔
  • 更新剩余次数前先判断自己的更新次数是否为最新,避免更新后次数反而变大的问题
  • 有小概率两人甚至三人同时查看剩余次数,导致重复抄写

Student.java

public class Student extends Thread{
    private String name;
    private Punishment punishment;

    public Student(String name,Punishment punishment){
        super(name);
        this.name = name;
        this.punishment = punishment;
    }

    public void copyWord(){
        int count = 0;
        String threadName = Thread.currentThread().getName();

        while(true){
            if(punishment.getLeftCopyCount() > 0){
                int leftCopyCount = punishment.getLeftCopyCount();
                leftCopyCount--;
                if(leftCopyCount<punishment.getLeftCopyCount()){
                    punishment.setLeftCopyCount(leftCopyCount);
                }
                System.out.println(threadName+"线程-" + name + "抄写" + punishment.getWordToCopy() + "。还要抄写" +
                        leftCopyCount + "次");
                count++;
            }else{
                break;
            }
        }
        System.out.println(threadName + "线程-" + name + "一共抄写了" + count + "次!");
    }
    @Override
    public void run(){
        copyWord();
    }
} 

StudentClient.java

public class StudentClient {
    public static void main(String[] args) {
        Punishment punishment = new Punishment(100,"internationalization");
        Student xiaoming = new Student("小明",punishment);
        xiaoming.start();
        Student xiaozhang = new Student("小张",punishment);
        xiaozhang.start();
        Student xiaozhao = new Student("小赵",punishment);
        xiaozhao.start();
    }
}

小赵线程-小赵一共抄写了34次!
小张线程-小张一共抄写了22次!
小明线程-小明一共抄写了44次!

例5:解决线程安全问题

[Java] 多线程

参考

java多线程是并发还是并行

https://blog.csdn.net/gxl1989225/article/details/84912017

[Java] 多线程

上一篇:Java基础之集合框架--Collections.reverse()方法


下一篇:Failed to convert value of type 'java.lang.String' to required type 'java.util.Date';