Java多线程

    xiaoxiao2025-06-25  5

    1.线程简介

    1.1什么是线程,多线程

    线程:程序中的一段相对独立运行的代码,执行指定的运算或者操作 多线程:多于一个以上的线程并行运行,执行各自的任务 注意:虽然每个线程都有自己的堆栈、程序计数器以及本地变量,但彼此之间并不是相互隔绝、独立存在

    1.2线程怎样工作

    这里要分为单处理器和多处理器分析了。对于多处理器而言多线程在系统中运行时不需要被不断地从单个处理器中调换,而是在多处理器中同时并行运行。对于单处理器,线程则需要不断地调换,但是处理器处理速度很快,因此给我们的感觉像是在并行运行一样。

    1.3线程的状态

    一个线程的创建一般都会经历五种状态,即start,runnable、sleeping、wating、stopped。线程在运行之后可能存在三种结果,即等待、睡眠、运行完毕结束其生命周期

    2.线程实列

    public class ThreadTest extends Thread{ public static void main(String[] args) { Thread thread = new Thread(); thread.start(); System.out.println(thread.getId()); System.out.println(thread.getName()); System.out.println(thread.getPriority()); System.out.println(thread.getState()); System.out.println(Thread.currentThread()); } }

    这样运行线程之后,除了选择打印的信息之外不会再显示其他内容。这是因为Thread的run()方法中并没有什么内容,需要根据具体需要自己继承实现

    public class ThreadTest extends Thread{ public void run(){ System.out.println("hello world" + this.getName()); } public static void main(String[] args) { ThreadTest[] threadT = new ThreadTest[10];//每次运行结果都不相同,可以借此更加清楚的理解线程 for(Thread th : threadT) { th = new ThreadTest(); th.start(); } } }

    除了继承Thread外我们还可以实现Runnable接口,具体实例如下 如何使用实现了Runnable的类,这里需要了解Thread类的几个构造方法

    方法名解释方法名解释Thread ()直接创建线程对象Thread(new Runnable())传入实现了Runnable接口的类对象Thread(new Runnable(), String threadName)除传入对象外,指定线程名Thread (String name)指定线程名

    我们选择第三个构造方法并且打印相关信息

    @Override class PrintHello implements{ public void run() { System.out.println("hello world"); } } public class ThreadTest{ public static void main(String[] args){ Thread threadR = new Thread(new PrintHello()); threadR.start(); } }

    3.线程控制

    3.1睡眠sleep()

    让制定线程睡眠指定时间,计时结束即进入准备运行状态

    public static void sleep(long millis) public static void sleep(long millis, int nanos)

    sleep()静态方法,且被重载,第二个方法nanos参数为指定线程额外将睡眠的纳秒数 具体实例

    class SleepTest extends Thread{ public void run() { System.out.println("继承了Thread类的run()"); } } public class ThreadSleepTest implements Runnable{ @Override public void run() { System.out.println("实现了Runnable接口的run()"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { SleepTest[] th1 = new SleepTest[10]; Thread[] th2 = new Thread[10]; for(int i = 0; i < 10; i++) { th1[i] = new SleepTest(); th2[i] = new Thread(new ThreadSleepTest()); th1[i].start(); th2[i].start(); } } }

    运行发现实现了Runnable接口的run()方法要晚于继承thread类的run()方法,原因是实现了Runabel接口的run()方法运行过程中睡眠了100毫秒。但当睡眠时间很短时Runnable的run()要早于Thread的run(),说明睡眠方法并不能做到绝对准确,原因是计时不可能做到绝对准确,还因为假设Runnable的run()总是先于Thread的run()执行,即使是睡眠了,但仍不能保证睡眠的线程一定会落后其他线程被调度

    3.2线程的优先级

    优先级用1-10之间数字表示,数值越大优先级越高,默认是5。 可以调用setPriority()方法来设置 public final void setPriority(), 因为是final修饰,因此继承Thread类是不可重写该方法 具体实例

    class Priority extends Thread { public void run() { System.out.println("继承了Thread类的run()"); } } public class ThreadPriorityTest implements Runnable{ @Override public void run() { System.out.println("实现了Runnable的run()"); } public static void main(String[] args) { Priority[] th1 = new Priority[10]; Thread[] th2 = new Thread[10]; for(int i = 0; i < 10; i++) { th1[i] = new Priority(); th2[i] = new Thread(new ThreadPriorityTest()); th1[i].setPriority(Thread.MAX_PRIORITY); th2[i].setPriority(Thread.MIN_PRIORITY); th1[i].start(); th2[i].start(); } } }

    Thread.MAX_PRIORITY是Runnable接口中的静态常量,运行后发现Thread的run()总是最后结束

    3.3线程的让步yield()和join()

    yield():当前运行的线程让出CPU,回到准备状态。这个方法具有不确定性,因为让出的CPU资源不一定被调度给哪个线程,有可能仍是这个线程 join():当前运行的线程让出CPU,知道另一个线程结束才恢复 具体实例

    Thread.yield() class JoinAndYield extends Thread { public void run() { System.out.println("继承了Thread类的run()"); } } public class ThreadJoinAndYield implements Runnable{ @Override public void run() { System.out.println("实现了Runnable的run()"); Thread.yield(); } public static void main(String[] args) { JoinAndYield[] th1 = new JoinAndYield[10]; Thread[] th2 = new Thread[10]; for(int i = 0; i < 10; i++) { th1[i] = new JoinAndYield(); th2[i] = new Thread(new ThreadJoinAndYield()); th1[i].start(); th2[i].start(); } } }

    运行后发现,结果同上面分析相同 join()

    class JoinAndYield extends Thread { public void run() { System.out.println("继承了Thread类的run()"); } } public class ThreadJoinAndYield implements Runnable{ @Override public void run() { System.out.println("实现了Runnable的run()"); } public static void main(String[] args) { JoinAndYield[] th1 = new JoinAndYield[10]; Thread[] th2 = new Thread[10]; for(int i = 0; i < 10; i++) { th1[i] = new JoinAndYield(); th2[i] = new Thread(new ThreadJoinAndYield()); th1[i].start(); try { th1[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } th2[i].start(); } } }

    运行后发现,Thread的run()总是先于Runnable的run()方法执行

    public class ThreadJoinAndYield extends Thread{ private static int sign = 1; private static double PI = 0.0; public void run() { for(long i = 1; i <10000000; i+=2) { PI += 4.0 * (double) sign / i; sign = -sign; } } public static void main(String[] args) throws InterruptedException { Thread demo = new ThreadJoinAndYield (); demo.start(); demo.join();//没有阻塞,主线程首先被执行,子线程没有得到执行 System.out.println(ThreadDaemonTest.PI); } }

    4.线程的重要性

    通过实例验证多线程的重要性,要求查找二维数组中最大值

    public class ThreadDemo extends Thread{ private double max = Integer.MIN_VALUE; private double[] array; public ThreadDemo(double[] array) { this.array = array; } public void run() { for(int i = 0; i < array.length; i++) { max = Math.max(max, array[i]); } } public double getMax() { return max; } public static void main(String[] args) throws InterruptedException { double[][] array = RandomArray.setArray(100, 200); double max = Integer.MIN_VALUE; ThreadDemo[] th = new ThreadDemo[10]; long endTime = 0, startTime = 0, time = 0; for(int i = 0; i < 10; i++) { th[i] = new ThreadDemo(array[i]); th[i].start(); } try { startTime = System.currentTimeMillis(); System.out.println("Start time is " + startTime); for(int i = 0; i < 10; i++) { th[i].join(); max = Math.max(max, th[i].getMax()); } endTime = System.currentTimeMillis(); System.out.println("End time " + endTime); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println("The max value is " + max); time = endTime - startTime; System.out.println("Completion time is " + time + "ms"); } } class RandomArray{ public static double[][] setArray(int row, int col){ double[][] array = new double[row][col]; for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { array[i][j] = Math.random() * 100; } } return array; } } class RandomArray{ public static double[][] setArray(int row, int col){ double[][] array = new double[row][col]; for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { array[i][j] = Math.random() * 100; } } return array; } } class Classic{ private double[][] array = RandomArray.setArray(10, 200); private double max = Integer.MIN_VALUE; public Classic() { getMax(); } public void getMax() { for(int i = 0; i < 10; i++) { for(int j = 0; j < 200; j++) { max = Math.max(max, array[i][j]); } } System.out.println("The max value is " + max); } } public class ThreadTest{ public static void main(String[] args) { long startTime = 0, endTime = 0, time = 0; startTime = System.currentTimeMillis(); System.out.println("Start time is " + startTime); new Classic(); endTime = System.currentTimeMillis(); System.out.println("End time " + endTime); time = endTime - startTime; System.out.println("Completion time is " + time + "ms"); } }

    多线程运行发现要比常规查找快很多,4-3ms

    最新回复(0)