java--多线程

1,java中线程的生命周期和5种状态

经典图

 线程的生命周期中有5种状态

01:新建状态 (new 一个线程),就是我们new 一个线程对象,此时线程是新建状态

  02:就绪状态(runnable),调用线程的 start()方法,线程就进入了就绪状态 ,调用start方法的线程并不一定会马上就开始执行,就绪状态表示线程做好了准备,随时等待cpu有资源的时候执行。

  03:运行状态(running),不多说,就是线程运行状态,

  04:阻塞状态(blocked):看上图,线程的阻塞状态有多种情况,阻塞状态就是线程由于某种原因停止了执行,

wait阻塞:等待阻塞,wait是object类的方法,可以指定一个等待的时间,当调用object的notify()或notifyAll()方法时,线程就会从阻塞状态进入到就绪状态,

 

public final void wait() throws InterruptedException {
        wait(0);
    }

synchronized阻塞:同步阻塞,线程在执行到synchronized 修饰的代码时,会求获取同步锁对象,当有别的线程占用锁的时候,获取锁对象失败,

 

就进入到同步阻塞状态

其他阻塞:thread.sleep()方法,join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、

或者I/O处理完毕时,线程重新转入就绪状态。

05:dead死亡状态,线程执行完毕,或者异常退出了,线程就死亡了

2.java中生成一个线程对象的几种方法

01、继承Thread类,重写润方法

class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println("线程:" + Thread.currentThread().getName() + "正在执行");
    }
}

02、实现runnable接口,实现run方法

 

 

class MyThreadRun implements Runnable{

    @Override
    public void run() {
        System.out.println("线程:" + Thread.currentThread().getName() + "正在执行");
    }
}

03、实现callable接口,实现call方法,使用这种方法线程会返回一个future对象,可以让线程返回数据

 

class MyCallable implements Callable<String> {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {

        return name;
    }

    @Override
    public String call() throws Exception {
        return name;
    }
}


3.synchronized 关键字

 

synchronized 修饰同步方法和同步代码块,用来保证在多线程环境下的线程安全,

同步代码块

 

public class TestSync {

    public void print(){
       synchronized (this){

            for (int i = 0; i < 5; i++) {
                System.out.println("TestSync--->"+i);
            }
        }
    }
    public static  void main(String[] args){
        TestSync testSync=new TestSync();
        Mythread mt1=new Mythread(testSync);
        Mythread mt2=new Mythread(testSync);
        mt1.start();
        mt2.start();
    }
}

class Mythread extends Thread{
    private TestSync testSync;

    public Mythread(TestSync testSync) {
        this.testSync = testSync;
    }

    @Override
    public void run() {
        testSync.print();
    }
}

执行结果: 可以看到是顺序执行的,在第一个线程获得锁的时候,其他线程就会进入阻塞状态,等待拥有锁对象的线程执行完毕,再去竞争这个锁,

 

谁抢到了锁,谁就执行,这里的this 表示以当前实例对象为锁,当然你也可以随便new 一个object 来当做所对象

TestSync--->0
TestSync--->1
TestSync--->2
TestSync--->3
TestSync--->4
TestSync--->0
TestSync--->1
TestSync--->2
TestSync--->3
TestSync--->4
去掉同步块

 

 public void print(){
      // synchronized (this){

            for (int i = 0; i < 5; i++) {
                System.out.println("TestSync--->"+i);
            }
       // }
    }

 

执行结果: 执行的顺序是无序的,两个线程交替执行

TestSync--->0
TestSync--->0
TestSync--->1
TestSync--->2
TestSync--->1
TestSync--->3
TestSync--->2
TestSync--->4
TestSync--->3
TestSync--->4

同步方法: 执行结果和上边相同,这里也是以实例对象为锁对象

 

public synchronized void print(){
      

            for (int i = 0; i < 5; i++) {
                System.out.println("TestSync--->"+i);
            }
     
    }


还有一种是修饰static方法,这时是以类对象为同步锁

 

 

  public  static synchronized void print(){


            for (int i = 0; i < 5; i++) {
                System.out.println("TestSync--->"+i);
            }

    }


4.wait 和sleep的区别

 

wait方法和sleep方法都可以让线程休眠指定的时间,区别就是sleep方法不会释放锁,wait会释放出锁

看代码

 

package threadTest;

/**
 * Created by LuTshoes on 2017/8/4 0004.
 * lutshoes@163.com
 */
public class TestThread {
    Object object = new Object();

    public void print() {
        synchronized (object) {
            for (int i = 0; i < 3; i++) {
                if (i == 1) {
                    try {
                        object.wait(2000);
                        //Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("当前线程:" + Thread.currentThread().getName() + "--->" + i);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestThread testThread = new TestThread();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                testThread.print();
            }
        });
        t1.start();
        Thread.sleep(1000);//让t2线程在t1之后启动
        t2.start();
    }
}

 

执行结果: 虽然在print方法里面加上了synchronized所,但是wait方法会释放object锁对象的控制,给了线程t2执行的机会
当前线程:Thread-0--->0
当前线程:Thread-1--->0
当前线程:Thread-0--->1
当前线程:Thread-0--->2
当前线程:Thread-1--->1
当前线程:Thread-1--->2

把wait方法换成sleep方法,执行结果,可以看到线程t1虽然休眠了2秒,执行完成但是t2却没有获得执行的机会,就是因为sleep不会释放锁的占有

当前线程:Thread-0--->0
当前线程:Thread-0--->1
当前线程:Thread-0--->2
当前线程:Thread-1--->0
当前线程:Thread-1--->1
当前线程:Thread-1--->2

thread.yeild 方法

Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,

让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。

        yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保

证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

      举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,

有可能是其他人先上车了,也有可能是Yield先上车了。

     但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,

最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。

5.java.util.concurrent包

这个包里面有很多在多线程环境下的工具类,比如 executors,executorService,threadLocal,concurrentHashMap

concurrentHashMap 具有hashTabl的功能,

executors类可以帮我们生成各种不同功能的线程池,

 

package threadTest;

/**
 * Created by LuTshoes on 2017/8/3 0003.
 * lutshoes@163.com
 */

import org.junit.Test;

import java.util.concurrent.*;


public class TashExecutorHolder {
    //创建一个可根据需要创建新线程的线程池,
    // 但是在以前构造的线程可用时将重用它们。
    // 对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。
    private ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    //创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
    /**
     * newFixedThreadPool的参数指定了可以运行的线程的最大数目,超过这个数目的线程加进去以后,
     * 不会运行。其次,加入线程池的线程属于托管状态,线程的运行不受加入顺序的影响。
     */
    private ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
    //创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
    private ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
    // 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);

    private ExecutorService callablePool = Executors.newFixedThreadPool(2);
    @Test
    public void testCachedThreadPool() {

        Thread t1 = new MyThread();
        Thread t2 = new MyThread();
        Thread t3 = new MyThread();
        cachedThreadPool.execute(t1);
        cachedThreadPool.execute(t3);
        cachedThreadPool.execute(t2);
       /* Future<?> submit = cachedThreadPool.submit(t1);
        Object o = null;
        try {
            o = submit.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(o);*/
    }

    @Test
    public void testSingleThreadPool() {
        Thread t1 = new MyThread();
        Thread t2 = new MyThread();
        Thread t3 = new MyThread();
        Thread t4 = new MyThread();
        singleThreadPool.submit(t1);
        singleThreadPool.submit(t2);
        singleThreadPool.submit(t3);
        singleThreadPool.submit(t4);
    }

    @Test
    public void testFixedThreadPool() {
        Thread t1 = new MyThread();
        Thread t2 = new MyThread();
        Thread t3 = new MyThread();
        Thread t4 = new MyThread();
        fixedThreadPool.submit(t1);
        fixedThreadPool.submit(t2);
        fixedThreadPool.submit(t3);
        fixedThreadPool.submit(t4);

    }

    /**
     * 带有返回值的线程callable
     */
    @Test
    public void testCallablePool(){

        Future<People> future = callablePool.submit((Callable) () -> {
            return new People("lujia");
        });
        People people = null;
        try {
            people = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(people.toString());
    }

    @Test
    public void testCallable(){
        MyCallable myCallable = new MyCallable();
        myCallable.setName("哈哈");

    }
}

class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println("线程:" + Thread.currentThread().getName() + "正在执行");
    }
}
class People {
    public People(String name) {
        this.name = name;
    }

    private String name;

    @Override
    public String toString() {
      return this.name;
    }
}
class MyThreadRun implements Runnable{

    @Override
    public void run() {
        System.out.println("线程:" + Thread.currentThread().getName() + "正在执行");
    }
}
class MyCallable implements Callable<String> {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {

        return name;
    }

    @Override
    public String call() throws Exception {
        return name;
    }
}

 

 

 

 

 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值