java Thread的探索(一)
来源:互联网 发布:无法访问家庭网络共享 编辑:程序博客网 时间:2024/06/11 21:38
一、总结一下Thread的方法
1.Thread的构造函数
1.1 Thread():无参构造
1.2 Thread(Runnable target)
1.3 Thread(ThreadGroup group ,Runnabletarget)
1.4 Thread(String name)
1.5 Thread(Runnable target,String name)
1.6 Thread(ThreadGroup group, Runnabletarget,String name)
1.7 Thread(ThreadGroup group,Runnabletarget,String name,long stactSize)
参数group:线程组
target:Runnable对象
name:线程名
stactSize:线程所需堆栈大小,如果为零表示忽略
2. Thread的静态方法:
2.1 currentThread():返回对当前执行对象的引用;
2.2 yield():执行yield()提示当前线程调度器愿意放弃当前所使用的处理器,当然调度器可以忽略这个提示(可以理解为你想让当前线程让步,但是愿不愿意让,具有不确定性)。
2.3 sleep(long millis):当前的线程以指定的毫秒数休眠(暂时停止执行),线程不会失去监视器的所有权(可以理解为不会释放该线程持有的对象锁),sleep(long millis),内部调用了sleep(long millis,int nanos)方法;
2.4 sleep(long millis,int nanos):当前的正在执行的线程以指的毫秒数(ms)加纳秒数(ns)休眠(暂时停止执行),线程不会失去监视器的所有权(1ms=106ns精度很高);
2.5 interrupted():测试当前线程是否被暂停,此方法清除线程的暂停状态。
3.Thread的非静态方法
3.1 start():线程执行方法,重复执行将会thrownew IllegalArgumentException,这是一个synchronized方法
3.2 interrupt():暂停该线程
3.3 isInterrupted():判断线程是否为暂停状态,线程的状态不受此方法的影响;
3.4 isAlive():判断线程是否活着的
3.5 setPriority(int newPriority):设置线程的优先级,默认优先级为5,最小为1,最大为10;
3.6 getPriority():获取线程的优先级;
3.7 setName(String name):设置线程名;
3.8 getName():获取线程名;
3.9 getThreadGroup():获取线程组
3.10 activeCount():返回当前线程及其子组线程中活动线程的估计值;
3.11 enumerate(Thread array[]):将当前的线程组及其子组中的每个活动线程复制到指定数组中,并返回放入线组的线程数;
3.12 join(long millis):等待此线程最多mills或者此线程在mills内结束。
join():等待此线程结束,内部调用的join(0);
join(long mills,int nanos):这个方法内部调用了join(longmills),只是等待时间为 mills+nanos;
3.13 setDaemon(boolean on):将此线程是否设置为守护线程,此方法必须在start()之前设置,否则报错;
3.14 isDaemon():判断此线程是否为守护线程;
3.15 checkAccess():确认当前线程是否有修改此线程的权限
3.16 getId():返回当前线程的id;
3.17 getState():返回当前线程的状态State.
二、实际操作
说一千道一万,不如自己来实际操作一下。首先来测试线程的暂停状态,先来看下一般的异常抛出
代码如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { File file = new File(Environment.getExternalStorageDirectory() + "/abcdef"); try { FileInputStream in = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread.start(); }empty运行结果08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: java.io.FileNotFoundException: /storage/emulated/0/abcdef: open failed: ENOENT (No such file or directory)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: at libcore.io.IoBridge.open(IoBridge.java:452)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: at java.io.FileInputStream.(FileInputStream.java:76)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: at com.wogu.threaddemo2.MainActivity$1.run(MainActivity.java:26)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: at java.lang.Thread.run(Thread.java:818)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: at libcore.io.Posix.open(Native Method)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: at libcore.io.IoBridge.open(IoBridge.java:438)08-17 11:13:03.425 6531-6573/threaddemo2 W/System.err: ... 3 more08-17 11:13:04.466 6531-6573/threaddemo2 W/System.err: java.io.FileNotFoundException: /storage/emulated/0/abcdef: open failed: ENOENT (No such file or directory)08-17 11:13:04.466 6531-6573/threaddemo2 W/System.err: at libcore.io.IoBridge.open(IoBridge.java:452)08-17 11:13:04.466 6531-6573/threaddemo2 W/System.err: at java.io.FileInputStream. (FileInputStream.java:76)08-17 11:13:04.466 6531-6573/threaddemo2 W/System.err: at com.wogu.threaddemo2.MainActivity$1.run(MainActivity.java:26)08-17 11:13:04.466 6531-6573/threaddemo2 W/System.err: at java.lang.Thread.run(Thread.java:818)
可以看到文件路径不存在,该线程每秒抛出一个FileNotFoundException异常
再看下thread2被暂停后会出现什么结果
empty private static final String TAG = "MainActivity"; private Thread thread1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); thread1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { Log.i(TAG, "当前线程名:" + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "thread1"); thread1.start(); //建立一个定时器2秒后暂停线程thread1 TimerTask task = new TimerTask() { @Override public void run() { Log.i(TAG, "线程暂停前状态:" + thread1.isInterrupted()); thread1.interrupt(); Log.i(TAG, "线程暂停后状态:" + thread1.isInterrupted()); } }; Timer timer=new Timer("checkThreadState"); timer.schedule(task,2000); }empty测试结果11:31:21.237 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:22.238 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:22.239 25594-25665/threaddemo2 I/MainActivity: 线程暂停前状态:false08-17 11:31:22.239 25594-25665/threaddemo2 I/MainActivity: 线程暂停后状态:true08-17 11:31:22.239 25594-25664/threaddemo2 W/System.err: java.lang.InterruptedException08-17 11:31:22.241 25594-25664/threaddemo2 W/System.err: at java.lang.Thread.sleep(Native Method)08-17 11:31:22.241 25594-25664/threaddemo2 W/System.err: at java.lang.Thread.sleep(Thread.java:1031)08-17 11:31:22.241 25594-25664/threaddemo2 W/System.err: at java.lang.Thread.sleep(Thread.java:985)08-17 11:31:22.241 25594-25664/threaddemo2 W/System.err: at com.wogu.threaddemo2.MainActivity$1.run(MainActivity.java:25)08-17 11:31:22.241 25594-25664/threaddemo2 W/System.err: at java.lang.Thread.run(Thread.java:818)08-17 11:31:22.241 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:23.241 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:24.242 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:25.242 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:26.242 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:27.242 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread108-17 11:31:28.243 25594-25664/threaddemo2 I/MainActivity: 当前线程名:thread1
thread2.isInterrupted()调用此方法后,查看日志后可以看到thread2的确暂停了,但是为什么只抛出一次InterruptedException异常。看了下Thread类,突然发现sleep(long millis,int nanos)调用了Thread.interrupted()方法(查看下),该方法具有清除了thread2线程的暂停状态的作用,所以第二次不会再出现异常。
emptypublic static void sleep(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("millis < 0: " + millis); } if (nanos < 0) { throw new IllegalArgumentException("nanos < 0: " + nanos); } if (nanos > 999999) { throw new IllegalArgumentException("nanos > 999999: " + nanos); } // The JLS 3rd edition, section 17.9 says: "...sleep for zero // time...need not have observable effects." if (millis == 0 && nanos == 0) { // ...but we still have to handle being interrupted. //此处调用了Thread.interrupted() if (Thread.interrupted()) { throw new InterruptedException(); } return; } long start = System.nanoTime(); long duration = (millis * NANOS_PER_MILLI) + nanos; Object lock = currentThread().lock; // Wait may return early, so loop until sleep duration passes. synchronized (lock) { while (true) { sleep(lock, millis, nanos); long now = System.nanoTime(); long elapsed = now - start; if (elapsed >= duration) { break; } duration -= elapsed; start = now; millis = duration / NANOS_PER_MILLI; nanos = (int) (duration % NANOS_PER_MILLI); } } }
再来看看join这个重载方法,join这个重载方法,归根结底还是join(long millis)。Join(long millis)内部是一个synchronized(lock){},而lock是Object对象,这就意味着Activity中所有其他线程都将暂停。直到获得Object对象锁的线程在设定的时间内已经结束,或者超过设定的时间(换句话来说就是等到该线程释放了Object对象锁)。代码如下:
empty @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TestThread testThread=new TestThread(); Thread thread2=new Thread(testThread,"Thread2"); thread2.start(); //主线程每秒打印一次 for (int i = 0; i < 5; i++) { Log.i(TAG, "当前线程名:" + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } private class TestThread implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++) { Log.i(TAG, "当前线程名:" + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }empty@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TestThread testThread=new TestThread(); Thread thread2=new Thread(testThread,"Thread2"); thread2.start(); //调用thread2 join() try { thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } //主线程每秒打印一次 for (int i = 0; i < 5; i++) { Log.i(TAG, "当前线程名:" + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } private class TestThread implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++) { Log.i(TAG, "当前线程名:" + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
未使用Thread2.join()运行日志如下,可以看到主线程和子线程交替运行
当前线程名:main
当前线程名:Thread2
当前线程名:main
当前线程名:Thread2
当前线程名:main
当前线程名:Thread2
当前线程名:main
当前线程名:Thread2
当前线程名:main
当前线程名:Thread2
在看下thread2使用join(),运行结果如何
当前线程名:Thread2
当前线程名:Thread2
当前线程名:Thread2
当前线程名:Thread2
当前线程名:Thread2
当前线程名:main
当前线程名:main
当前线程名:main
当前线程名:main
当前线程名:main
通过日志可以看到,只有等thread2运行完了,主线程才开始运行.在看看使用join(2000)看下运行日志如何
08-17 13:43:47.584 31157-31231/com.threaddemo2 I/MainActivity: 当前线程名:Thread2
08-17 13:43:48.584 31157-31231/com.threaddemo2 I/MainActivity: 当前线程名:Thread2
08-17 13:43:49.584 31157-31157/com.threaddemo2 I/MainActivity: 当前线程名:main
08-17 13:43:49.585 31157-31231/com.threaddemo2 I/MainActivity: 当前线程名:Thread2
08-17 13:43:50.585 31157-31231/com.threaddemo2 I/MainActivity: 当前线程名:Thread2
08-17 13:43:50.585 31157-31157/com.threaddemo2 I/MainActivity: 当前线程名:main
08-17 13:43:51.585 31157-31157/com.threaddemo2 I/MainActivity: 当前线程名:main
08-17 13:43:51.585 31157-31231/com.threaddemo2 I/MainActivity: 当前线程名:Thread2
08-17 13:43:52.585 31157-31157/com.threaddemo2 I/MainActivity: 当前线程名:main
08-17 13:43:53.586 31157-31157/com.threaddemo2 I/MainActivity: 当前线程名:main
因为thread2是每秒打印一次日志,thread2.join(2000)了2秒,所以打印2次后,Object对象锁释放了。其实这种现象很好解释,因为join()内部的同步方法更深层次调用的是lock.wait(long millis)方法。再来看看Object对象的wait(long millis),说的简单点就是mills毫秒后释放Object对象锁。(未完待续)
- java Thread的探索(一)
- 《探索C++多线程》:thread源码(一)
- Java线程Thread(一)
- Java Swing 探索(一)LayoutManager
- Java Swing 探索(一)LayoutManager
- JAVA GC机制探索(一)
- Java学习 - Thread Synchronized (一)
- Java多线程之Thread(一)
- **JAVA** Thread系列一
- 【RPC框架探索】(一)ICE框架的探索
- Thread的interrupt、isInterrupted、interrupted源码探索
- Java的Thread(笔记)
- 探索OLAM的精髓(一)
- 前后端分离的探索(一)
- 数据库索引选择的探索(一)
- 《探索C++多线程》:thread源码(二)
- java写出大数据(千万级别)的excel探索(一)
- java并发[一]探索获取合理的并发数
- 修复Ubuntu unable access to dev/sdb- 无法挂载Windows下文件夹问题
- 享元模式
- 虚拟ubuntu系统中浏览器的音频播放问题
- 深度学习在美团点评推荐平台排序中的运用
- 暴利截流,各路神仙让我等沾沾仙气
- java Thread的探索(一)
- HDU 4121 Xiangqi
- HDU 6127 Hard challenge
- 函数
- 网络编程问题
- java验证电话号码
- Android 自定义控件零基础(1)
- TCP/IP四层模型和OSI七层模型的概念
- Spring的理解