进程与线程:
什么是进程: 就是应用程序在运行时期, 所占用的内存空间区域.
一个程序也可以说是一个进程, 开辟的内存可能不是连续的 0-88,99-120 的内存块, 这样的话可能就造成了其他程序和当前的程序的数据错乱, 还有一些什神奇的错误, 这时候伟大的工程师, 采用了虚拟内存, 就是虚拟出来连续的内存, 指向非连续的内存这地址)
什么是线程: 是进程中的单个顺序控制流, 是一条执行路径.
单线程: 一个进程只有一个可执行的路径
多线程: 一个进程有多个可执行的路径
线程的实现方式
线程是依托于进程而存在的, 而进程是系统创建出去的, java 并不能操作系统, 但是可以调 C/C++, 实现创建进程, 从而可以实现线程.(线程进程都是由操作系统, 依靠 JVM 找操作系统, 才能实现线程的功能)
Thread 类: 继承
- public class MyThread extends Thread {
- @Override
- public void run() {
- super.run();
- // 线程一般执行的是耗时任务 尤其是在 Android 端
- for (int i = 0; i <100; i++) {
- System.out.println(i);
- }
- }
- }
- // 开启线程
- public class ThreadDemo {
- public static void main(String[] args) {
- MyThread myThread = new MyThread();
- myThread.start();
- }
- }
Runnable : 实现
- public class RunnableDemo implements Runnable {
- @Override
- public void run() {
- // 线程一般执行的是耗时任务 尤其是在 Android 端
- for (int i = 0; i < 100; i++) {
- System.out.println(i);
- }
- }
- }
- // 开启线程
- public class ThreadDemo {
- public static void main(String[] args) {
- RunnableDemo runnableDemo = new RunnableDemo ();
- //Theand 的构造方法 可以出入一个 runnable 对象
- new Thread(runnableDemo ).start();
- }
- }
两种方式对比: 实现接口, 避免单继承局限性
这样我们就开启了两个线程,
那么, 我们在继承 Thread 类或实现 Runnable 类之后, 为什么要重写 run()方法呢?
因为不是类中的所有代码都需要被线程执行的 (个人理解继承 Thread 或实现 Runnable 的子类, 不一定全是要 执行在 run() 方法里, 可能存在其他的自定义方法, 和成员变量). 而这个时候, 为了区分哪些代码能够被线程执行, java 提供了 Thread 类中的 run()用来包含那些被线程执行的代码.
设置和获取线程的名字
Thread 类的基本获取和设置方法
public final String getName(): 获取线程的名称.
public final void setName(String name): 设置线程的名称
- public class ThreadDemo {
- public static void main(String[] args) {
- RunnableDemo runnableDemo = new RunnableDemo();
- Thread thread = new Thread(runnableDemo);
- thread.setName("001");
- System.out.println(thread.getName());
- thread.start();
- MyThread myThread = new MyThread();
- myThread.setName("002");
- System.out.println(myThread.getName());
- myThread.start();
- // 获取当前正在执行的线程名字
- System.out.println(Thread.currentThread().getName());
- }
- }
线程的操作
public static void sleep(long millis): 线程休眠
- public class MyThread extends Thread {
- @Override
- public void run() {
- super.run();
- // 线程一般执行的是耗时任务 尤其是在 Android 端
- try {
- // 当前线程被执行的时候, 会每次睡眠一秒
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- for (int i = 0; i < 100; i++) {
- System.out.println(i);
- }
- }
- }
public final void wait() : 线程等待
- public class MyThread extends Thread {
- @Override
- public void run() {
- super.run();
- // 线程一般执行的是耗时任务 尤其是在 Android 端
- synchronized (this) {
- try {
- // 次线程就会被挂起, 放弃 CPU 的执行权和释放锁, 等待 notify()
- wait();
- // wait(1000);
- // wait(2000, 1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- for (int i = 0; i < 100; i++) {
- System.out.println(i);
- }
- }
- }
sleep()和 wait()的区别:
使用上
从使用角度看, sleep 是 Thread 线程类的静态方法, 而 wait 是 Object 顶级类的费静态方法().
sleep 可以在任何地方使用(指的是当前执行的线程休眠), 而 wait 只能在同步方法或者同步块中使用
CPU 及资源锁释放
sleep,wait 调用后都会暂停当前线程并让出 CPU 的执行时间, 但不同的是 sleep 不会释放当前持有的对象的锁资源, 到时间后会继续执行, 而 wait 会放弃所有锁并需要 notify/notifyAll 后重新获取到对象锁资源后才能继续执行.
异常捕获
sleep 需要捕获或者抛出异常, 而 wait/notify/notifyAll 不需要.
为什么线程方法等待, 唤醒写了 Object 类?
notify 等待, 唤醒本锁上的线程, 必须有锁的支持, 锁是任意对象, 将 wait,notify 方法写了 Object 类, 保证任意对象锁都可以调用线程, 等待唤醒方法
public final void stop(): 中断线程
- public class StopThreadDemo {
- public static void main(String[] args) {
- Thread t = new Thread(new StopThread());
- t.start();
- t.stop();
- }
- }
- class StopThread implements Runnable {
- @Override
- public void run() {
- while (true) {
- System.out.println("run.........");
- }
- }
- }
线程无任何输出, 直接停止了, 不再继续执行了
public void interrupt(): 中断线程
- public class InterruptThreadDemo {
- public static void main(String[] args) {
- InterruptThread t = new InterruptThread();
- t.start();
- try {
- // 如果 5 秒 不醒来 我就弄死你
- Thread.sleep(5000);
- t.interrupt();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- class InterruptThread extends Thread {
- @Override
- public void run() {
- try {
- Thread.sleep(10000);
- } catch (InterruptedException e) {
- System.out.println("线程被终止了");
- }
- System.out.println("run.........");
- }
- }
但是 interrupt()方法执行后, 它会终止线程的状态, 还会继续执行 run 方法里面的代码.
线程的终止 1 stop 过时 2,interrupt 3, 标记执行循环, run 方法结束
public final void join(): 线程加入
- public class JoinThread {
- public static void main(String[] String) {
- JoinRunnable joinRunnable1 = new JoinRunnable();
- JoinRunnable joinRunnable2 = new JoinRunnable();
- JoinRunnable joinRunnable3 = new JoinRunnable();
- Thread t1=new Thread(joinRunnable1);
- t1.setName("我是 1");
- Thread t2=new Thread(joinRunnable2);
- t2.setName("我是 2");
- Thread t3=new Thread(joinRunnable3);
- t3.setName("我是 3");
- t1.start();
- try {
- t1.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- t2.start();
- t3.start();
- }
- }
- class JoinRunnable implements Runnable {
- @Override
- public void run() {
- for (int i = 0; i < 10; i++) {
- System.out.println(Thread.currentThread().getName().toString());
- }
- }
- }
等待该线程终止, 使用了 join 方法的线程, 会一直运行结束, 其他线程抢 CPU 的资源
public static void yield(): 线程礼让
- /**
- * 线程的让步 yield
- */
- public class YieldThreadDemo {
- public static void main(String[] args) {
- YieldRunnable yieldRunnable = new YieldRunnable();
- Thread t0 = new Thread(yieldRunnable);
- Thread t1 = new Thread(yieldRunnable);
- t0.start();
- t1.start();
- }
- }
- class YieldRunnable implements Runnable {
- @Override
- public void run() {
- for (int x = 0; x < 100; x++) {
- Thread.yield();
- System.out.println(Thread.currentThread().getName() + "....run");
- }
- }
- }
这个方法暂停当前正在执行的线程对象, 并执行其他线程, 出现互相谦让的状态.
让多个线程的执行更和谐, 但是不能靠它保证一人一次.
public final void setDaemon(boolean on): 守护线程
- /**
- * setDaemon(true) 守护线程
- */
- public class DaemomThreadDemo {
- public static void main(String[] args) {
- Thread t0 = new Thread(new DaemomRunnable());
- t0.setDaemon(true);// 线程 t0 是 main 线程的守护线程, 如果 main 执行完或者 main 线程终止, main 的守护线程都死亡
- t0.start();
- }
- }
- class DaemomRunnable implements Runnable {
- @Override
- public void run() {
- for (int i = 30; i> 0; i++) {
- System.out.println("run........");
- }
- }
- }
当线程设为 A 线程的守护线程, A 死亡后, 所有的守护线程都死亡
线程的运行状态图
Thread.PNG
第一次画图, 见笑了,
模拟火车站卖票, 引出多线程的数据安全问题
- public class ThreadDemo {
- public static void main(String[] args) {
- RunnableDemo runnableDemo1 = new RunnableDemo();
- RunnableDemo runnableDemo2 = new RunnableDemo();
- RunnableDemo runnableDemo3 = new RunnableDemo();
- new Thread(runnableDemo1).start();
- new Thread(runnableDemo2).start();
- new Thread(runnableDemo3).start();
- }
- }
- public class RunnableDemo1 implements Runnable {
- // 定义一百张车票
- private int mTicket = 100;
- @Override
- public void run() {
- while (mTicket> 0) {
- // 每出售一张 -- 操作
- System.out.println(Thread.currentThread().getName() + "出售车票 =" + mTicket-- + "张");
- }
- }
- }
data.jpg
多线程状态下, 数据出现了问题, 怎么解决多线程下的数据安全问题, 请看下节
如有出入, 往大佬扶正, 谢谢!!!!
来源: http://www.jianshu.com/p/aa5b3e99ceea