多线程学习(一)
来源:互联网 发布:社交网络对社会的影响 编辑:程序博客网 时间:2024/05/20 22:01
线程的五种状态
1.新建状态 New
Thread thread=new Thread();
2.就绪状态 Runnable
可执行状态
thread.start();
处于就绪状态的线程,随时可能被CPU调度执行。
3.运行状态Running
线程获取CPU权限进行执行
注意:线程只能从就绪状态转化为运行状态
4.阻塞状态 Blocked
因为某种原因线程放弃CPU执行权
暂时停止运行
直到线程进入就绪状态时,才有可能转化为运行状态
01.等待阻塞
通过调用wait()方法
让线程等待某工作的完成
02.同步阻塞
线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
(03) 其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5. 死亡状态(Dead) : 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
Object类,定义了wait(), notify(), notifyAll()等休眠/唤醒函数。
Thread类,定义了一些列的线程操作函数。例如,sleep()休眠函数, interrupt()中断函数, getName()获取线程名称等。
synchronized,是关键字;它区分为synchronized代码块和synchronized方法。synchronized的作用是让线程获取对象的同步锁。
java中实现线程的两种基本方法
1.编写继承Thread类的类,重写run()方法
2.编写实现Runnable接口的类,实现run()方法
其中观看源码可知,Thread类实现了Runnable接口
publicclass Thread implements Runnable
package wangcc.thread.base;import org.junit.Test;/** * @ClassName: Demo * @Description: TODO(这里用一句话描述这个类的作用) * @author wangcc * @date 2017年6月25日 下午8:16:23 start() : * 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。 run() : * run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程! */public class Demo { @Test public void testThread() { Thread mythread = new MyThread("mythread"); System.out.println(Thread.currentThread().getName() + "call mythread run()"); mythread.run(); System.out.println(Thread.currentThread().getName() + "call mythread starat()"); mythread.start(); }}
package wangcc.thread.base;public class MyThread extends Thread { public MyThread(String name) { super(name); } public void run() { // Thread.currentThread() native method System.out.println(Thread.currentThread().getName() + " is running"); }}
package wangcc.thread.base;public class Demo1 { public static void main(String[] args) { // TODO Auto-generated method stub Runnable runnable = new MyRunnable(); Thread thread1 = new Thread(runnable, "1"); Thread thread2 = new Thread(runnable, "2"); thread1.start(); thread2.start(); }}
package wangcc.thread.base;public class MyRunnable implements Runnable { @Override public void run() { // TODO Auto-generated method stub synchronized (this) { try { for (int i = 0; i < 5; i++) { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " loop " + i); } } catch (InterruptedException e) { // TODO: handle exception } } }}
上面我们可以看到thread.start()使得线程处于可执行状态Runnable,即随时可以获得CPU执行权,运行线程,此时run()方法便被调用。
start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。
run() : run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程!
public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ //如果不是就绪状态,就抛出异常 if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } //本地方法 private native void start0();
我们通过源码来分析一下上面例子中的代码为什么可以实现线程。
Runnable runnable = new MyRunnable(); Thread thread1 = new Thread(runnable, "1"); Thread thread2 = new Thread(runnable, "2"); thread1.start(); thread2.start();
这里的Thread的构造方法为
public Thread(Runnable target, String name) { init(null, target, name, 0); }
private void init(ThreadGroup g, Runnable target, String name, long stackSize) { if (name == null) { throw new NullPointerException("name cannot be null"); } Thread parent = currentThread(); SecurityManager security = System.getSecurityManager(); if (g == null) { /* Determine if it's an applet or not */ /* If there is a security manager, ask the security manager what to do. */ if (security != null) { g = security.getThreadGroup(); } /* If the security doesn't have a strong opinion of the matter use the parent thread group. */ if (g == null) { g = parent.getThreadGroup(); } } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */ g.checkAccess(); /* * Do we have the required permissions? */ if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon(); this.priority = parent.getPriority(); this.name = name.toCharArray(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); }
再看看Thread的run方法
/* What will be run. */ private Runnable target; public void run() { if (target != null) { target.run(); } }
可以很清楚的看出,其实调用的就是实现Runnable接口的类的run方法,所以可以通过实现Runnable接口,再用该类完成Thread的初始化可以实现线程。
所以,按照我的理解来看,其实现实线程就一种方法,那就是实现Runnable接口。
- 多线程学习(一)
- 多线程学习(一)
- 多线程学习(一)
- 多线程学习(一)
- 多线程学习(一)
- 多线程学习(一)
- 学习多线程(一)认识多线程
- 多线程学习(一)什么是多线程?
- linux多线程学习(一)
- linux多线程学习(一)
- 多线程的学习(一)
- linux多线程学习(一)
- linux多线程学习(一)
- linux多线程学习(一)
- java多线程学习(一)
- JAVA多线程学习(一)
- java多线程学习(一)
- 多线程学习(一)----CreateThread
- EL表达式
- cmake:msvc编译第三方库时使用/MT静态库连接c/c++ runtime library
- Vue.js
- Servlet使用分析
- jQueryEasyUI实现房贷计算器详细教程3--EasyUI部分
- 多线程学习(一)
- C# 获得%ProgramData% 路径
- 请不要让环境限制你的成长——让你的努力落地有声
- Web前端-HeadFirst-CH8-字体种类
- Android开发中JavaBean类和序列化知识的理解
- leetcode 515. Find Largest Value in Each Tree Row
- C语言 特殊数问题 回文数 素数 亲密数 水仙花数
- WebLogic
- 建造者模式