java多线程

java多线程

线程生命周期

  1. 新建状态:
        顾名思义,就是新建一个线程。处于新建状态的线程有自己的内存空间,通过调用start方法进入就绪状态。
  2. 就绪状态:
        这时已经具备了运行条件,但还没有分配到CPU。等待状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动作称之为“cpu调度”。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法。
  3. 运行状态:
        运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
        此时线程失去了cpu资源,就会又从运行状态变为就绪状态。当发生如下情况是,线程会从运行状态变为阻塞状态:
    ①、线程调用sleep方法主动放弃所占用的系统资源
    ②、线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
    ③、线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有
    ④、线程在等待某个通知(notify)
    ⑤、程序调用了线程的suspend方法将线程挂起。不过该方法容易导致死锁,所以程序应该尽量避免使用该方法。
    当线程的run()方法执行完,或者被强制性地终止,例如出现异常,或者调用了stop()、desyory()方法等等,就会从运行状态转变为死亡状态。
  4. 阻塞状态:
        在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行。
  5. 死亡状态:
        当线程的run()方法执行完,或者被强制性地终止,就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。 如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

多线程的实现方式

java中实现多线程的方式有四种:
  1. 继承Thread类,重写run方法
  2. 实现Runnable接口,重写run方法。
  3. 通过Callable和FutureTask创建线程。
  4. 通过线程池创建线程
  前两种可以归为一类,都是通过重写run方法,run方法的返回类型为void,无返回值。由于java单继承,类继承了Thread,会导致无法继承其他类,同时继承Thread类实际上是无法达到资源共享的目的的,所以在实际开发中更多的是实现Runnable接口。后面两种有返回值可以归结为一类。

方法1:继承Thread类

package com.zhang.Thread.thread;

/**
 * @Description : 继承Thread类
 * @Author : zhangMing
 * @Date : Created in 上午11:06 2018/3/20
 */
public class ThreadTest extends Thread {

    volatile int i ;
    @Override
    public void run() {
        for (; i < 10 ; i ++) {
            System.out.println(Thread.currentThread().getName() + "执行了第"+i+"次");
        }
    }

    public static void main(String[] arg){
        ThreadTest threadTest = new ThreadTest();
        ThreadTest threadTest1 = new ThreadTest();
        ThreadTest threadTest2 = new ThreadTest();
        ThreadTest threadTest3 = new ThreadTest();
        threadTest.start();
        threadTest1.start();
        threadTest2.start();
        threadTest3.start();
    }
}

方式2:实现Runnable接口

package com.zhang.Thread.runnable;

/**
 * @Description : 实现runnable接口
 * @Author : zhangMing
 * @Date : Created in 上午10:56 2018/3/20
 */
public class RunnableTest implements Runnable{
    int i;
    public void run() {
        for (; i < 10 ; i ++){
            System.out.println(Thread.currentThread().getName()+"执行了第"+i+"次");
        }
    }

    public static void main(String[] arg){
        RunnableTest runnableTest = new RunnableTest();
        Thread thread = new Thread(runnableTest,"线程");
        Thread thread1 = new Thread(runnableTest,"线程1");
        thread.start();
        thread1.start();
    }
}

方法3:实现Callable接口

package com.zhang.Thread.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * @Description : 实现callable接口
 * @Author : zhangMing
 * @Date : Created in 上午11:09 2018/3/20
 */
public class CallableTest implements Callable {

    int i ;

    public Object call() throws Exception {
        for (; i < 10 ; i ++){
            System.out.println(Thread.currentThread().getName()+"执行了第"+i+"次");
        }
        return Thread.currentThread().getName()+"执行完毕";
    }

    public static void main(String[] arg){
        CallableTest callableTest = new CallableTest();
        FutureTask futureTask = new FutureTask(callableTest);
        FutureTask futureTask1 = new FutureTask(callableTest);
        new Thread(futureTask,"aa").start();
        new Thread(futureTask1,"bb").start();
        try {
            System.out.println(futureTask.get());
            System.out.println(futureTask1.get());
        }catch (Exception e){

        }
    }
}

方法4:线程池

package com.zhang.Thread.ThreadPool;

import com.zhang.Thread.callable.CallableTest;
import com.zhang.Thread.runnable.RunnableTest;
import com.zhang.Thread.thread.ThreadTest;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

/**
 * @Description : 线程池
 * @Author : zhangMing
 * @Date : Created in 上午10:55 2018/3/20
 */
public class ThreadPool {

    static ExecutorService executorService;

    public static void main(String[] arg){
        //官方推荐,会自动创建 销毁
        executorService = Executors.newCachedThreadPool();
        executorService.execute(new ThreadTest());
        executorService.execute(new RunnableTest());
        FutureTask futureTask = new FutureTask(new CallableTest());
        executorService.execute(futureTask);
        try {
            System.out.println(futureTask.get());
        }catch (Exception e){

        }
        //关闭
        executorService.shutdown();
    }
}

  执行后会发现结果有时候会和自己想的有些差别,这就是线程不安全的问题。下一篇会详解一下线程安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值