前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java线程(一)—— 新建线程

java线程(一)—— 新建线程

作者头像
逝兮诚
发布2019-10-30 13:37:39
5200
发布2019-10-30 13:37:39
举报
文章被收录于专栏:代码人生代码人生

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/luo4105/article/details/72902328

多线程

多线程实际是调用的操作系统中多线程操作的接口,在多线程的操作系统中,线程是可以并行存在的,即在某一时刻,cpu可以同时运行多个线程(多核CPU)。操作系统对多线程的调度对于java来说是不可见,对程序员来说是不可知的,所以在多线程运行时会存在很多问题。

多线程编程的原因:节约资源,当多个用户在用一时间段操作服务器时,必须使用多线程才能达到极快的响应。

生命周期

线程有5种状态

1.新建状态:新建一个线程对象。

2.就绪状态:线程对象运行start()方法,进入就绪队列,等待jvm虚拟机调度机的调度。

3.运行状态:就绪线程执行run()方法,进入运行状态,根据run()方法的代码线程会进入就绪、阻塞、死亡状态。

4.阻塞状态:线程执行sleep、join等。

5.死亡状态:线程完成任务或执行其他命令时。

进程与线程

一个进程可以存在一个或多个线程。

线程是一条有序的操作。

Java线程实现

实现Runnable接口或继承Thread类

实现run函数,自己写start函数,在函数中初始化Thread对象并调用run()方法。

Runnable接口实现的线程是没有返回值的。

实现Runbable接口方式

代码语言:javascript
复制
public classRunnableDemo implements Runnable {
 
    private Thread thread;
    private String threadName;
 
    public RunnableDemo(String threadName) {
       this.threadName = threadName;
    }
 
    @SuppressWarnings("static-access")
    public void run() {
       System.out.println(threadName + "启动");
       for (int i = 0; i < 4; i++) {
           System.out.println(threadName);
           try {
              thread.sleep(500);
           }catch(InterruptedException e) {
              e.printStackTrace();
              continue;
           }
       }
       System.out.println(threadName + "关闭");
    }
 
    public void start() {
       this.thread = new Thread(this, threadName);
       this.thread.start();
    }
}

测试类

代码语言:javascript
复制
public classRunnableDemoTest {
 
    public static void main(String[] args) {
       RunnableDemor1 = new RunnableDemo("线程1");
       r1.start();
       RunnableDemor2 = new RunnableDemo("线程2");
       r2.start();
    }
}

实现Callable接口

Callable接口可以拿到线程返回值

代码语言:javascript
复制
public classCallableThreadTest implements Callable<Integer>{
 
    @Override
    public Integer call() throws Exception {
       int i = 0;
       for (; i < 100; i++) {
           System.out.println(Thread.currentThread().getName()+ i);
       }
       return i;
    }
 
    public static void main(String[] args) {
       CallableThreadTestctt= newCallableThreadTest();
       FutureTask<Integer>ft = new FutureTask<>(ctt);
       for (int i = 0; i < 100; i++) {
           System.out.println(Thread.currentThread().getName()+ " 循环变量i的值" + i);
           if (i == 20) {
              new Thread(ft, "有返回值的线程").start();
           }
       }
       try {
           System.out.println("子线程的返回值:"+ft.get());
       }catch(InterruptedException | ExecutionException e) {
           e.printStackTrace();
       } 
    }
}

实现线程安全的单例模式

先写一个线程不安全的写法

代码语言:javascript
复制
private static Bank bank;
 
private Bank() {
}
 
public static Bank getBank() {
         if(bank == null) {
                   bank= new Bank();
         }
         returnbank;
}

假设线程A和线程B同时访问到if (bank == null) ,且bank目前为空时,线程A和B都会去执行bank = new Bank();,那么单例就失效了。

解决方法一:方法加上同步锁关键字修饰

代码语言:javascript
复制
public synchronizedstaticBank getBankSY() {
    if (bank == null) {
       bank = new Bank();
    }
    return bank;
}

当使用同步锁时,所有线程执行getBankSY()方法都会阻塞,一次只能允许一个线程执行该方法。但这样十分消耗资源,如果单例已经初始化,这时再进行同步就没有必要了。可以使用双重检测。

代码语言:javascript
复制
private staticvolatileBank bank;
public synchronizedstaticBank getBankDC() {
    if (bank == null) {
       synchronized (Bank.class) {
           if (bank == null) {
              bank = new Bank();
           }
       }
    }
    return bank;
}

当第一检测不为空时,就不会进入同步状态,阻塞线程了。

线程同步工具CountDownLatch

当一个线程需要等待其他线程全部执行完毕后,它再去执行时,可以使用CountDownLatch。先初始化一个CountDownLatch对象,每个线程结束时,执行.countDown方法,在需要等待的线程中执行.await()方法,它会阻塞该线程,知道所有countDown的线程执行完。

代码语言:javascript
复制
public voidtrueSinglon() {
    CountDownLatchcdl= newCountDownLatch(2);
    new Thread() {
       public void run() {
           b1 = Bank.getBankDC();
           cdl.countDown();
       }
    }.start();
    new Thread() {
       public void run() {
           b2 = Bank.getBankDC();
           cdl.countDown();
       }
    }.start();
    try {
       cdl.await();
       System.out.println( "双重验证单例返回值比较:" + (b1==b2));
    }catch(InterruptedException e) {
       e.printStackTrace();
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-06-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 多线程
  • 生命周期
  • 进程与线程
  • Java线程实现
    • 实现Runbable接口方式
      • 实现Callable接口
      • 实现线程安全的单例模式
      • 线程同步工具CountDownLatch
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档