Java学习笔记(十八)

JNLP API:

要想从文件中读取数据, 需要使用 FileOpenService。如果想要打开一个特定的文件, 需要使用 ExtendedService。要想在默认浏览器中显示一个文档, 就需要使用 BasicService 接口。

可以调用 PersistenceService 中的 create 方法建立一个新的键。

线程:

由于 Runnable 是一个函数式接口,可以用 lambda 表达式建立一个实例:
Runnable r = ()-> { task code };

不要调用 Thread 类或 Runnable 对象的 run 方法。 直接调用 run 方法, 只会执行同一个线程中的任务, 而不会启动新线程。应该调用 Thread.start 方法。这个方法将创建一个执行 run 方法的新线程。

某些线程是如此重要以至于应该处理完异常后, 继续执行,而不理会中断。但是,更普遍的情况是,线程将简单地将中断作为一个终止的请求。

如果在每次工作迭代之后都调用 sleep 方法(或者其他的可中断方法,) islnterrupted 检测既没有必要也没有用处。如果在中断状态被置位时调用 sleep 方法,它不会休眠。相反,它将清除这一状态(!)并拋出 IntemiptedException。因此, 如果你的循环调用 sleep,不会检测中断状态。

interrupted 方法是一个静态方法, 它检测当前的线程是否被中断。 而且, 调用 interrupted 方法会清除该线程的中断状态。另一方面,islnterrupted 方法是一个实例方法,可用来检验是否有线程被中断。调用这个方法不会改变中断状态.

线程可以有如下 6 种状态:
•New (新创建)
•Runnable (可运行)
•Blocked (被阻塞)
•Waiting (等待)
•Timed waiting (计时等待)
•Terminated (被终止)
要确定一个线程的当前状态, 可调用 getState 方法

线程因如下两个原因之一而被终止:
•因为 run 方法正常退出而自然死亡。
•因为一个没有捕获的异常终止了 run 方法而意外死亡。

可以用 setPriority 方法提高或降低任何一个线程的优先级。

可以用 setUncaughtExceptionHandler 方法为任何线程安装一个处理器。也可以用 Thread类的静态方法setDefaultUncaughtExceptionHandler 为所有线程安装一个默认的处理器。

如果不为独立的线程安装处理器,此时的处理器就是该线程的 ThreadGroup 对象。
ThreadGroup 类实现 Thread.UncaughtExceptionHandler 接口。它的 uncaughtException 方法做如下操作:
1 ) 如果该线程组有父线程组, 那么父线程组的 uncaughtException 方法被调用。
2 ) 否则, 如果 Thread.getDefaultExceptionHandler 方法返回一个非空的处理器, 则调用该处理器。
3 ) 否则,如果 Throwable 是 ThreadDeath 的一个实例, 什么都不做。
4 ) 否则,线程的名字以及 Throwable 的栈轨迹被输出到 System.err 上。

如果使用锁, 就不能使用带资源的 try 语句。

一个锁对象可以有一个或多个相关的条件对象。
sufficientFunds.signalAll();这一调用重新激活因为这一条件而等待的所有线程。一旦锁成为可用的,它们中的某个将从 await 调用返回, 获得该锁并从被阻塞的地方继续执行。此时, 线程应该再次测试该条件。 由于无法确保该条件被满足—signalAll 方法仅仅是通知正在等待的线程:此时有可能已经满足条件, 值得再次去检测该条件。

如果所有其他线程被阻塞, 最后一个活动线程在解除其他线程的阻塞状态之前就调用 await 方法, 那么它也被阻塞。没有任何线程可以解除其他线程的阻塞,那么该程序就挂起了。

应该何时调用 signalAll 呢? 经验上讲, 在对象的状态有利于等待线程的方向改变时调用signalAll。

另一个方法 signal, 则是随机解除等待集中某个线程的阻塞状态。

当一个线程拥有某个条件的锁时, 它仅仅可以在该条件上调用 await、signalAll 或signal 方法。

有关锁和条件的关键之处:
•锁用来保护代码片段, 任何时刻只能有一个线程执行被保护的代码。
•锁可以管理试图进入被保护代码段的线程。
•锁可以拥有一个或多个相关的条件对象。
•每个条件对象管理那些已经进入被保护的代码段但还不能运行的线程。

如果一个方法用 synchronized关键字声明,那么对象的锁将保护整个方法。也就是说,要调用该方法,线程必须获得内部的对象锁。
换句话说,
public synchronized void method()
{
method body
}
等价于
public void method()
{
this.intrinsidock.lock();
try
{
method body
}
finally { this.intrinsicLock.unlock(); }
}

内部对象锁只有一个相关条件。wait 方法添加一个线程到等待集中,notifyAU /notify方
法解除等待线程的阻塞状态。换句话说,调用 wait 或 notityAll 等价于
intrinsicCondition.await();
intrinsicCondition.signalAIl();

将静态方法声明为 synchronized 也是合法的。

内部锁和条件存在一些局限。包括:
•不能中断一个正在试图获得锁的线程。
•试图获得锁时不能设定超时。
•每个锁仅有单一的条件, 可能是不够的。

•最好既不使用 Lock/Condition 也不使用 synchronized 关键字。在许多情况下你可以使用 java.util.concurrent 包中的一种机制,它会为你处理所有的加锁。
•如果 synchronized 关键字适合你的程序, 那么请尽量使用它,这样可以减少编写的代码数量,减少出错的几率。
•如果特别需要 Lock/Condition 结构提供的独有特性时,才使用 Lock/Condition。

有时程序员使用一个对象的锁来实现额外的原子操作, 实际上称为客户端锁定( clientside locking) 。但客户端锁定是非常脆弱
的,通常不推荐使用

猜你喜欢

转载自blog.csdn.net/qq_38022739/article/details/89279643