多线程能够提高任务完成的效率,
具体使用:
有两个整数变量,分别对着两个整数变量自增10亿次,分别使用一个线程和两个线程来观察时间的变化
package Thread; import java.util.Scanner; public class Demo7 { private static final long count = 10_0000_0000; public static void serial() { long beg = System.currentTimeMillis(); long a = 0; long b = 0; for(int i = 0; i < count; i ++) { a ++; } for(int i = 0; i < count; i ++) { b ++; } long end = System.currentTimeMillis(); System.out.println((end - beg) + "ms"); } public static void concurrency() throws InterruptedException{ long beg = System.currentTimeMillis(); Thread thread1 = new Thread(() -> { long a = 0; for(int i = 0; i < count; i ++) { a ++; } }); thread1.start(); Thread thread2 = new Thread(() -> { long b = 0; for(int i = 0; i < count; i ++) { b ++; } }); thread2.start(); thread1.join(); thread2.join(); long end = System.currentTimeMillis(); System.out.println((end - beg) + "ms"); } public static void main(String[] args) throws InterruptedException { serial(); concurrency(); } }
Thread类的其它属性和方法
Thread(String name)
,这个东西是给线程起名字,起一个什么样子的名字不影响线程本身的执行,仅仅影响到程序员的调试,可以借助一些工具可以看到每个线程的名字,很容易在调试的时候对线程做出区分,可以用jconsole
来观察线程的名字
** 中断线程**
线程停下来的关键是让对应的run方法执行完(还有一个特殊的是main这个线程,对于main来说,得是main方法执行完,线程就完了)
- 可以手动的设置一个标志位(自己创建的变量,boolean),来控制线程是否要执行结束
代码实现:
public class Main { private static boolean isQuit = false; public static void main(String[] args) { Thread thread = new Thread(() -> { while(! isQuit) { System.out.println("hello thread!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } isQuit = true; } }
这种实现的方法并不严谨,假如有很多线程都要用这个标志位怎么办?
- 更好的方法是用一个Thread中内置的一个标志位来判定,可以通过两种方法来实现
Thread.interrupted()
,这是一个静态的方法
Thread.currentThread().isInterrupt()
,这是一个实例的方法,其中的currentThread
就是获取当前线程的实例
使用样例:
public class Main { public static void main(String[] args) { Thread thread = new Thread(() -> { while(! Thread.currentThread().isInterrupted()) { System.out.println("hello thread!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } }
这个代码绝大部分都是在休眠状态,此处的中断是希望立即产生效果的,如果线程已经是阻塞状态下,此时设置标志位就不能起到及时唤醒的效果
调佣
t.interrupt()
,这个方法可能产生两种情况
- 如果线程是出于就绪状态,就是设置线程的标志位为true
- 如果线程出于阻塞状态,就会触发一个异常,应该在异常的时候直接退出即可
线程等待
多个线程之间调度顺序是不确定的,线程之间的执行是按照调度器来来安排的,这个过程可视为是“无序,随机”,这样不太好,有些时候我们需要控制线程之间的顺序,线程等待就是一种控制线程执行顺序的手段,此处的线程等待,主要是控制线程结束的先后顺序
join
,调佣join的时候,那个线程调用的join,那个线程就会阻塞等待,知道对应的线程执行完毕为止(对应的run方法执行完)
主要有:
1. 线程的创建
2. 线程的终结
3. 线程的等待
4. 线程获取引用
5. 线程的休眠