多线程编程

进程VS线程VS多线程

多线程编程

  • 继承Thread类

  • 实现Runnable接口

继承Thread类

// mythread.java
public class Mythread extends Thread{
    @Override
    public void run(){
        System.out.println("My thread");
    }
}

// run.java
public class Run {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        mythread.start();
        System.out.println("End");
    }
}

代码运行结果与代码的执行顺序或调用顺序无关(线程的随机性)
线程随机性

// mythread.java
public class Mythread extends Thread{
    @Override
    public void run(){
        try {
            for (int i = 0; i < 10; i++){
                int time = (int) (Math.random()*1000);
                Thread.sleep(time);
                System.out.println("Mythread run=" + Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// run.java
public class Run {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        mythread.setName("Mythread");
        mythread.start();
        try {
            for (int i = 0; i < 10; i++){
                int time = (int) (Math.random()*1000);
                Thread.sleep(time);
                System.out.println("Main run=" + Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

此处myThread.start()替换为myThread.run()的区别在于start()和main的线程为异步,换成run()后为同步,需要等到main的线程来调用,即等run()方法中的代码执行完后才可以执行后面的代码。
执行start()方法的顺序不代表线程启动的顺序,代码如下:

// mythread.java
public class Mythread extends Thread{
    private int i;
    public Mythread(int i) {
        super();
        this.i = i;
    }
    @Override
    public void run(){
        System.out.println(i);
    }
}

// run.java
public class Run {
    public static void main(String[] args) {
        Mythread mt1 = new Mythread(1);
        Mythread mt2 = new Mythread(2);
        Mythread mt3 = new Mythread(3);
        Mythread mt4 = new Mythread(4);
        Mythread mt5 = new Mythread(5);
        Mythread mt6 = new Mythread(6);
        Mythread mt7 = new Mythread(7);
        Mythread mt8 = new Mythread(8);
        Mythread mt9 = new Mythread(9);
        Mythread mt10 = new Mythread(10);
        mt1.start();
        mt2.start();
        mt3.start();
        mt4.start();
        mt5.start();
        mt6.start();
        mt7.start();
        mt8.start();
        mt9.start();
        mt10.start();
    }
}

实现Runnable接口

// myRunnable.java
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("Run");
    }
}

// run.java
public class Run {
    public static void main(String[] args) {
        Runnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
        System.out.println("Run end");
    }
}

实例变量与线程安全

线程不同享

多个线程分别处理自己对应的count

// mythread.java
public class Mythread extends Thread{
    private int count = 5;
    public Mythread(String name) {
        super();
        this.setName(name);
    }
    @Override
    public void run(){
        super.run();
        while (count > 0){
            count--;
            System.out.println(" 由 " + currentThread().getName() + " 计算, count=" + count);
        }
    }
}

// run.java
public class Run {
    public static void main(String[] args) {
        Mythread a = new Mythread("A");
        Mythread b = new Mythread("B");
        Mythread c = new Mythread("C");
        a.start();
        b.start();
        c.start();
    }
}

运行结果:

 由 A 计算, count=4
 由 B 计算, count=4
 由 C 计算, count=4
 由 B 计算, count=3
 由 B 计算, count=2
 由 B 计算, count=1
 由 B 计算, count=0
 由 A 计算, count=3
 由 C 计算, count=3
 由 C 计算, count=2
 由 C 计算, count=1
 由 C 计算, count=0
 由 A 计算, count=2
 由 A 计算, count=1
 由 A 计算, count=0
线程共享

多个线程共同处理一个count

// mythread.java
public class Mythread extends Thread{
    private int count = 5;
    @Override
    public void run(){
        super.run();
        count--;
        System.out.println(" 由 " + currentThread().getName() + " 计算, count=" + count);
    }
}

// run.java
public class Run {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        Thread a = new Thread(mythread,"A");
        Thread b = new Thread(mythread,"B");
        Thread c = new Thread(mythread,"C");
        Thread d = new Thread(mythread,"D");
        Thread e = new Thread(mythread,"E");
        a.start();
        b.start();
        c.start();
        d.start();
        e.start();
    }
}

运行结果:

 由 A 计算, count=3
 由 E 计算, count=1
 由 C 计算, count=2
 由 B 计算, count=3
 由 D 计算, count=0

结果产生非线程安全问题。
某些JVM中,i–操作为3步:

  1. 取原有i值。

  2. 计算i-1。

  3. 对i进行赋值。

加synchronized改为线程安全:

// mythread.java
public class Mythread extends Thread{
    private int count = 5;
    @Override
    synchronized public void run(){
        super.run();
        count--;
        System.out.println(" 由 " + currentThread().getName() + " 计算, count=" + count);
    }
}

// run.java
public class Run {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        Thread a = new Thread(mythread,"A");
        Thread b = new Thread(mythread,"B");
        Thread c = new Thread(mythread,"C");
        Thread d = new Thread(mythread,"D");
        Thread e = new Thread(mythread,"E");
        a.start();
        b.start();
        c.start();
        d.start();
        e.start();
    }
}

运行结果:

 由 A 计算, count=4
 由 C 计算, count=3
 由 E 计算, count=2
 由 D 计算, count=1
 由 B 计算, count=0

另一个非线程安全的例子,解决方法加synchronized关键字

// loginServlet.java 模拟servlet组件
public class LoginServlet {
    private static String usernameRef;
    private static String passwordRef;
    public static void doPost(String username, String password){
        try{
            usernameRef = username;
            if(username.equals("a")){
                Thread.sleep(5000);
            }
            passwordRef = password;
            System.out.println("username=" + usernameRef + " password=" + password);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

// alogin.java
public class ALogin extends Thread{
    @Override
    public void run(){
        LoginServlet.doPost("a","aa");
    }
}

// blogin.java
public class BLogin extends Thread{
    @Override
    public void run(){
        LoginServlet.doPost("b","bb");
    }
}
// run.java
public class Run {
    public static void main(String[] args) {
        ALogin a = new ALogin();
        a.start();
        BLogin b = new BLogin();
        b.start();
    }
}

运行结果:

username=b password=bb
username=b password=aa

加synchronized关键字后:

synchronized public static void doPost(String username, String password){
        try{
            usernameRef = username;
            if(username.equals("a")){
                Thread.sleep(5000);
            }
            passwordRef = password;
            System.out.println("username=" + usernameRef + " password=" + password);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }

运行结果:

username=a password=aa
username=b password=bb
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值