Java核心技术第十四章——线程

1. 使用线程给其他任务提供机会

可以将移动球的代码放置在一个独立的线程中, 运行这段代码可以提高弹跳球的响应能力。实际上,可以发起多个球, 每个球都在自己的线程中运行。
由于每个线程都有机会得以运行,所以在球弹跳期间, 当用户点击Close 按钮时, 事件调度线程将有机会关注到这个事件, 并处理“ 关闭” 这一动作。

   Runnable runnable = () -> { 
       try
       {  
          for (int i = 1; i <= STEPS; i++)
          {
             ball.move(comp.getBounds());
             comp.repaint();
             Thread.sleep(DELAY);
          }
       }
       catch (InterruptedException e)
       {
       	System.out.println("Interrupt");
       }
    };
	 Thread thread = new Thread(runnable);
	 thread.start();

2. 带资源的try语句

      try (Scanner in = new Scanner(file, "UTF-8"))
      {
         int lineNumber = 0;
         while (in.hasNextLine())
         {
            lineNumber++;
            String line = in.nextLine();
            if (line.contains(keyword)) 
               System.out.printf("%s:%d:%s%n", file.getPath(), lineNumber, line);
         }
      }
   }

try 块退出时,会自动调用res.close()。
如果不用带资源的try语句,代码会变得很繁琐

	  	  Scanner in = new Scanner(file, "UTF-8");
	      try
	      {
	         int lineNumber = 0;
	         while (in.hasNextLine())
	         {
	            lineNumber++;
	            String line = in.nextLine();
	            if (line.contains(keyword)) 
	               System.out.printf("%s:%d:%s%n", file.getPath(), lineNumber, line);
	         }
	      }finally {
	    	  try {
	        	 in.close();
	    	  }catch (Exception e) {
				// TODO: handle exception
			}
		}

3. 匿名对象

语法上: 只创建对象,但是不用变量来接收
匿名对象只适合对方法的一次调用,因为调用多次就会产生多个对象,不如用有名字的对象
匿名对象的使用:

  1. 匿名对象也是一个对象,具有对象的所有功能
  2. 每一次使用匿名对象时,都是一个新的对象, 每次创建匿名对象都是不同的对象,一个匿名对象,只能使用一次,即匿名对象只能调用一次匿名对象
  3. 只在堆内存中开辟空间,而不存在栈内存的引用

4. violatile关键字

Java中violate关键字详解(2)?真正了解violate

1.volatile保证可见性

即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

线程本身并不直接与主内存进行数据的交互,而是通过线程的工作内存来完成相应的操作。这也是导致线程间数据不可见的本质原因。因此要实现volatile变量的可见性,直接从这方面入手即可。对volatile变量的写操作与普通变量的主要区别有两点:

  1. 修改volatile变量时会强制将修改后的值刷新的主内存中。

  2. 修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。

通过这两点就可以很好的解决可见性问题

1.volatile保证有序性

volatile之所以能够阻止指令重排,是因为底层JVM里面利用了内存屏障来实现的,内存屏障主要有三点功能

  1. 它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
  2. 它会强制将对缓存的修改操作立即写入主存;
  3. 如果是写操作,它会导致其他CPU中对应的缓存行无效

但是volatile不能保证原子性

使用 volatile 关键字的场景:
synchronized 关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而 volatile 关键字在某些情况下性能要优于synchronized ,但是要注意 volatile 关键字是无法替代synchronized 关键字的,因为 volatile 关键字无法保证操作的原子性。

通过关键字 sychronize 可以防止多个线程进入同一段代码,在某些特定场景中, volatile 相当于一个轻量级的 sychronize ,因为不会引起线程的上下文切换,但是使用 volatile 必须满足两个条件:
① 对变量的写操作不依赖当前值,如多线程下执行 i++ ,是无法通过 volatile 保证结果准确性的。
② 该变量没有包含在具有其他变量的不变式中,实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态

关键字-transient、volatile、strictfp总结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值