多线程学习(一)

来源:互联网 发布:社交网络对社会的影响 编辑:程序博客网 时间: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接口。

原创粉丝点击