Java多线程编程核心技术——Java多线程技能

1.程序、进程、线程三者的概念

程序:为完成某一特定任务或实现某种功能,使用某种语言编写的彝族指令的集合。
进程:是操作系统结构的基础;一次程序的执行;是一个程序及其数据在处理机上顺序执行所发生的活动;是程序在数据集合上运行的过程,它是系统进行分配和调度的一个独立单位。(正在运行的程序)
线程:进程中独立运行的子任务。

2.线程的创建

  • 继承Thread类
package com.ashley.thread.test1;
//创建Thread类的子类
public class MyThread extends Thread {
	//重写run()
    @Override
    public void run() {
    	super.run();
        System.out.println("MyThread********");
    }
}
package com.ashley.thread.test1;

public class Main {

    public static void main(String[] args) {
   		//创建Thread类的子类的对象
        MyThread mythread = new MyThread();
        //通过此对象调用start()
        mythread.start();//启动当前线程;调用当前线程的run()
  		System.out.println("运行结束!!!!!!!!");
    }
}

运行结果:
在这里插入图片描述

注意:
上述代码,按照正常的顺序先调用了start(),所以应该先调用Mythread类中的run(),先打印“MyThread********”,再打印main()中的“运行结束!!!!!!!!”,但结果却相反,说明在使用多线程技术的时候,代码的运行结果与代码执行顺序或调用顺序是无关的

线程的调用具有随机性:

package com.ashley.thread.Exer;

public class ThreadTest 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("run=" + currentThread().getName());
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

package com.ashley.thread.Exer;

public class Run {
    public static void main(String[] args) {
        try {
            ThreadTest thread = new ThreadTest();
            thread.setName("MyThread");//给新创建的线程命名
            thread.start();//启动创建的线程,调用run()
            for (int i = 0; i < 10; i++) {
                int time = (int) (Math.random() * 1000);
                Thread.sleep(time);//让线程处于阻塞状态,规定时间到了,重新返回runnable状态
                System.out.println("run=" + Thread.currentThread().getName());
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

某一次运行结果:
在这里插入图片描述
线程启动的顺序与start()执行顺序无关:

package com.ashley.thread.Exer1;

public class MyThread extends Thread {
    private int i;

    public MyThread(int i) {
        super();
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println(i);
    }
}

package com.ashley.thread.Exer1;

public class Main {
    public static void main(String[] args) {
        MyThread t11 = new MyThread(1);
        MyThread t12 = new MyThread(2);
        MyThread t13 = new MyThread(3);
        MyThread t14 = new MyThread(4);
        MyThread t15 = new MyThread(5);
        MyThread t16 = new MyThread(6);
        MyThread t17 = new MyThread(7);
        MyThread t18 = new MyThread(8);
        MyThread t19 = new MyThread(9);
        MyThread t110 = new MyThread(10);
        MyThread t111 = new MyThread(11);
        MyThread t112 = new MyThread(12);
        MyThread t113 = new MyThread(13);

        t113.start();
        t112.start();
        t111.start();
        t110.start();
        t19.start();
        t18.start();
        t17.start();
        t16.start();
        t15.start();
        t14.start();
        t13.start();
        t12.start();
        t11.start();
    }
}

某一次运行结果:
在这里插入图片描述

  • 实现Runnable接口
package com.ashley.thread.test4;

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("运行中~~~");
    }
}

package com.ashley.thread.test4;

public class Run {
    public static void main(String[] args) {
        Runnable runnable =new MyRunnable();
        Thread thread =new Thread(runnable);
        thread.start();
        System.out.println("运行结束!!!");
    }
}

运行结果:
在这里插入图片描述

3.实例变量与线程安全

共享数据的情况:多个线程同时访问同一个变量

package com.ashley.thread.test4;

public class MyThread1 extends Thread {
    private int count=5;

    @Override
    public void run() {
        super.run();
        count--;
        System.out.println("由线程" + this.currentThread().getName()+"计算, count=" + count);
    }
}
package com.ashley.thread.test4;

public class Main1 {
    public static void main(String[] args) {
        MyThread1 myThread = new MyThread1();
        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();
    }
}

某一次的运行结果:
在这里插入图片描述
由上述运行结果可以看出,线程D和线程E都打出了2,说明线程D和线程E同时对count进行了处理,产生了“非线程安全问题”。
在某些JVM中,i- -的操作分为三步执行:
(1)取得原有i值;
(2)计算i-1;
(3)对i进行赋值。
在这三个过程中,如果有多个线程同时访问,那么一定会出现非线程安全问题
非线程安全问题:多个线程对同一个对象中的同一个实例变量进行操作时会出现值被更改、值不同步的情况,进而影响程序的执行流程。

如果想要打印的结果不相等,且依次递减:

package com.ashley.thread.test5;

/**
 * @author ashley
 * @date 2019/9/27-20:07
 */
public class MyThread extends Thread {
    private int count =5;

    @Override
    //通过在run方法前加synchronized关键字,使多个线程在执行run方法时,以排队的方式处理
    synchronized public void run() {
        super.run();
        count --;
        System.out.println("由线程" + Thread.currentThread().getName()+"计算");
    }
}

不共享数据的情况:每个线程自己访问自己的变量

package com.ashley.thread.test4;

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("由线程" + this.currentThread().getName()+"计算, count=" + count);
        }
    }
}

package com.ashley.thread.test4;


public class Main {
    public static void main(String[] args) {
        MyThread t1 = new MyThread("A");
        MyThread t2 = new MyThread("B");
        MyThread t3 = new MyThread("C");

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

    }
}

某一次运行结果:
在这里插入图片描述
未完待续。。。。。

发布了49 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ashleyjun/article/details/101480540