Java编程--多线程(多线程常用的操作方法)
一.线程的命名与取得
所有线程程序的执行,每次都是不同的运行结果,因为它会根据自己的情况进行资源抢占。所以如果要想区分每一个线程,就必须依靠线程的名字。对于线程名字一般在启动之前进行定义,不建议对已经启动的线程进行名称更改或为不同的线程设置同名情况。
若想进行线程名称的操作,可以使用Thread类的如下方法:
构造方法: |
|
设置名字: |
public final void setName(String name):改变线程名称,使之与参数 name 相同。 |
取得名字: |
public final String getName():返回该线程的名称。 |
对于线程名字的操作会出现一个问题:这些方法是属于Thread里的,但是如果换回到线程类(Runnable子类),这个类并没有继承Thread类。若想取得线程名字,那么能够取得的就是当前执行本方法的线程名字。
在Thread类中提供有取得当前线程对象的方法:
public static Thread currentThread():返回对当前正在执行的线程对象的引用。
【范例】没有设置名字,观察线程的命名。
class MyThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } } public class Test { public static void main(String[] args) { MyThread mt = new MyThread(); new Thread(mt).start(); new Thread(mt).start(); new Thread(mt).start(); } }
运行结果:
结论:在实例化Thread对象的时候没有为其设置名字会自动进行编号命名。
【范例】设置名字。
class MyThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } } public class Test { public static void main(String[] args) { MyThread mt = new MyThread(); new Thread(mt,"A").start(); new Thread(mt).start(); new Thread(mt,"C").start(); new Thread(mt).start(); new Thread(mt,"B").start(); } }
运行结果:
【案例】在main方法中通过创建的线程对象直接调用run()方法。
class MyThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } } public class Test { public static void main(String[] args) { MyThread mt = new MyThread(); new Thread(mt,"A").start(); mt.run(); // 直接调用run()方法,main } }
运行结果:
结论:发现主方法就是一个线程(main线程),则所有在主方法上创建的线程实际上都可以将其表示为子线程。
通过以上代码发现,线程其实一直都存在(main方法就是主线程),但是进程去哪了呢?
每当使用java命令去解释一个程序类的时候,对于操作系统而言,都相当于启动了一个新的进程,而main只是新进程中的一个子线程而已。
【问题】每一个JVM进程启动的时候至少启动几个线程?
答:(1)一个main线程:程序的主要执行,以及启动子线程;(2)gc线程:负责垃圾收集。
二.线程的休眠
线程休眠指的是让线程的执行速度稍微变慢一点。
public static void sleep(long millis) throws InterruptedException:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
【范例】观察休眠的特点。
class MyThread implements Runnable { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ",i = " + i); } } } public class Test { public static void main(String[] args) { MyThread mt = new MyThread(); new Thread(mt, "A").start(); new Thread(mt, "B").start(); new Thread(mt, "C").start(); } }
运行结果:
结论:发现线程执行的速度变慢。
默认情况下休眠的时候若设置了多个线程对象,则所有的线程对象将一起进入(先后顺序不同,间隔太短,实际上有区别)到run()方法。
三.线程优先级
1. 线程优先级:越高的优先级,越有可能先执行。在Thread类中提供了两种方法:
(1)设置优先级:
public final void setPriority(int newPriority):更改线程的优先级。
(2)取得优先级:
public final int getPriority():返回线程的优先级。
2. 发现设置和取得优先级都使用了int类型数据,对于此内容有三种类型取值。
(1)最低优先级:
public static final int MIN_PRIORITY(1)
(2)中等优先级:
public static final int NORM_PRIORITY(5)
(3)最高优先级:
public static final int MAX_PRIORITY(10)
【范例】设置优先级。
class MyThread implements Runnable { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ",i = " + i); } } } public class Test { public static void main(String[] args) { MyThread mt = new MyThread(); Thread t1 = new Thread(mt, "A"); Thread t2 = new Thread(mt, "B"); Thread t3 = new Thread(mt, "C"); t1.setPriority(Thread.MAX_PRIORITY); // 设置优先级 t2.setPriority(Thread.MIN_PRIORITY); t1.start(); t2.start(); t3.start(); } }
【范例】查看主线程优先级
public class Test1 { public static void main(String[] args) { System.out.println(Thread.currentThread().getPriority()); // 5 } }
结论:主线程属于中等优先级(5)。
总结:
1. Thread.currentThread()可以取得当先线程对象;
2. Thread.sleep()主要用来休眠,感觉像一起休眠,但是实际上有先后顺序;
3. 优先级越高的线程对象越有可能先执行。(操作记的意义不大)