Java线程总结(二)

线程池优化多线程编程

在Java中的对象是使用new来进行创建的,如果对象的创建量少还好,当创建大量生命周期短的对象时,使用new这种方式效率是比较低下的。使用池技术可以解决这种问题。如数据库连接使用数据库连接池可以大大提高效率,而线程也有线程池。

下面例子中可以看出使用线程池和不使用线程池的效率差别,一种使用普通方式创建5000个生命周期短的线程,另一种是通过线程池技术来创建。

@Test

 public void TheandTest() {

         Runtime run = Runtime.getRuntime();// 创建Runtime对象

         run.gc();// 运行垃圾回收器

         long freeMemory = run.freeMemory();// 获得当前虚拟机的空闲内存

         long currentTime = System.currentTimeMillis();// 获得当前虚拟机的时间

         for (int i = 0; i < 5000; i++) {// 独立运行1000个线程

             new Thread(new TempThread()).start();//这里作简单的运算

         }

         System.out.println("不使用线程池方式创建5000个线程所占用的内存:" + (freeMemory - run.freeMemory()) + "字节");// 查看内存的变化

         System.out.println("不使用线程池方式创建5000个线程所消耗的时间:" + (System.currentTimeMillis() - currentTime) + "毫秒");// 查看时间的变化

        

         run.gc();// 运行垃圾回收器

         freeMemory = run.freeMemory();// 获得当前虚拟机的空闲内存

         currentTime = System.currentTimeMillis();// 获得当前虚拟机的时间

// 创建线程池 3代表线程池的线程数

         ExecutorService executorService = Executors.newFixedThreadPool(3);

         for (int i = 0; i < 5000; i++) {// 使用线程池运行5000个线程

             executorService.submit(new TempThread());

         }

         System.out.println("使用线程池运行5000个线程所占用的内存:" + (freeMemory - run.freeMemory()) + "字节");// 查看内存的变化

         System.out.println("使用线程池创建5000个线程所消耗的时间:" + (System.currentTimeMillis() - currentTime) + "毫秒");// 查看时间的变化

    }

运行输出

不管是创建占用的内存还是所用的时间,使用线程池创建的效率都是非常高的。

在使用完线程池后,需要调用ExecutorService接口中定义的shutdownNow()方法终止线程池。

Executors(java.util.concurrent):ExecutorExectorServiceThreadFactory等类提供工厂和方法。上面例子中使用了newFixedThqreadPool()方法创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。

如果一个线程池中有多个处于可运行的线程,当向线程添加RunnableCallable接口对象时,会有一个线程执行runcall方法,方法执行后,此时线程并没有终止,而是可运行状态,等待新的任务。

线程插入(加入)

在某些需求中,存在线程A,但业务需要插入线程B,并要线程B先执行完成,再执行线程A,此时可以使用Thread类的join()方法来完成。

Java虚拟机允许程序并发地运行多个执行线程。 join方法是Thqead类的一个静态方法,有3种形式

join()等待调用方法的线程终止

join(long mills)等待该调用方法的线程终止时间最长为mills毫秒

join(long mills,int nanos)等待调用该方法的线程终止时间最长为mills毫秒加nanos纳秒

注:如果有线程中断了运行中的join()方法线程,则会抛出interruptedException异常

下面这个类实现了Runnable接口,并在run()方法中每隔0.5秒输出一句语句。

public class ThreanJoinDemo implements Runnable {

    @Override

    public void run() {

        for (int i = 1; i < 10; i++) {

            try {

              //线程休眠0.5

                Thread.sleep(500);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

            System.out.println("我是插队:" + i + "");

        }

    }

}

再新建一个类,编写main方法,使用上面的ThreanJoinDemo类创建一个新的线程,并使用join()方法中途加入线程。

public static void main(String[] args) {

//创建新的线程

       Thread thread = new Thread(new ThreanJoinDemo());

        thread.start();//启动线程

        for (int i = 1; i < 10; i++) {

            try {

                Thread.sleep(100);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

            System.out.println( "正常排队"+ i + "");

            try {

                thread.join();//加入线程

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

运行效果

实现线程同步

多线程开发中,同步方法是比较常用的。同步方法就是有synchronized关键字修饰的方法,

synchronized修饰的方法就是同步方法,被线程调用时锁住该方法,只有这个线程执行完这个方法才能解锁,被其他线程调用,执行完后再开锁。synchronized可以修饰方法,修饰代码块,但是不能修饰构造器、成员变量等。synchronized修饰静态方法的话,如果调用该静态方法会锁住整个类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值