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. 匿名对象
语法上: 只创建对象,但是不用变量来接收
匿名对象只适合对方法的一次调用,因为调用多次就会产生多个对象,不如用有名字的对象
匿名对象的使用:
- 匿名对象也是一个对象,具有对象的所有功能
- 每一次使用匿名对象时,都是一个新的对象, 每次创建匿名对象都是不同的对象,一个匿名对象,只能使用一次,即匿名对象只能调用一次匿名对象
- 只在堆内存中开辟空间,而不存在栈内存的引用
4. violatile关键字
Java中violate关键字详解(2)?真正了解violate
1.volatile保证可见性
即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
线程本身并不直接与主内存进行数据的交互,而是通过线程的工作内存来完成相应的操作。这也是导致线程间数据不可见的本质原因。因此要实现volatile变量的可见性,直接从这方面入手即可。对volatile变量的写操作与普通变量的主要区别有两点:
-
修改volatile变量时会强制将修改后的值刷新的主内存中。
-
修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。
通过这两点就可以很好的解决可见性问题
1.volatile保证有序性
volatile之所以能够阻止指令重排,是因为底层JVM里面利用了内存屏障来实现的,内存屏障主要有三点功能
- 它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
- 它会强制将对缓存的修改操作立即写入主存;
- 如果是写操作,它会导致其他CPU中对应的缓存行无效
但是volatile不能保证原子性
使用 volatile 关键字的场景:
synchronized 关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而 volatile 关键字在某些情况下性能要优于synchronized ,但是要注意 volatile 关键字是无法替代synchronized 关键字的,因为 volatile 关键字无法保证操作的原子性。
通过关键字 sychronize 可以防止多个线程进入同一段代码,在某些特定场景中, volatile 相当于一个轻量级的 sychronize ,因为不会引起线程的上下文切换,但是使用 volatile 必须满足两个条件:
① 对变量的写操作不依赖当前值,如多线程下执行 i++ ,是无法通过 volatile 保证结果准确性的。
② 该变量没有包含在具有其他变量的不变式中,实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态