创建线程有哪几种方式分别是?
a.为一个进程创建多个线程。有三种方式
1.继承Thread类创建一个子线程
myThread.setName("李刚1"); // 给线程取一个名字
/** 拿到当前线程的名称 */
String name = Thread.currentThread().getName();
优点:写法简单,其他都是缺点。
缺点:线程已经继承一个类,再不能继承其他类了。
2.实现Runnable接口创建一个子线程
优点:可以继承其他类,多个Thread对象可以使用同一个target来处理。
3.实现Callable接口创建一个子线程。
优点:可以继承其他类,多个Thread对象可以使用同一个target来处理。
线程可以有执行结果,线程可以把异常往外抛出去 。
线程同步的方式有哪些?
为了保证线程同步,一共有3种方式:
a. 同步代码块。
synchronized(acct) {
// 同步代码块
}
synchronized后面括号里的对象叫“同步监视器、monitor”。
任何线程进入“同步代码块”之前, 必须先对“同步监视器、monitor”加锁(自动完成)
同步会导致性能下降。
虽然Java的语法,可用任何对象作为同步监视器,但一定要记住:
实际上只能选择“竞争资源”作为同步监视器。
当你正确地选择了“竞争资源”作为同步监视器之后,执行流程如下:
对“竞争资源”加锁 → 进入临界区、访问修改“竞争资源” → 对“竞争资源”解锁
——这是一个通用的设计哲学:
对共享资源加锁 → 修改 → 修改完成后,解锁。其他线程再次进来。
b.同步方法
被synchronized修饰的方法,就是同步方法。
对于同步方法而言,如果是实例方法, 使用this作为同步监视器;
如果是类方法,使用该类本身作为同步监视器。
通常来说,应该在“竞争资源”类的里面定义同步方法。
同步方法、同步代码块的逻辑是完全相同的,区别是同步代码块需要显式指定“竞争资源”作为同步监视器。
同步方法则直接定义定义“竞争资源”的实现类中,此时this(竞争资源)作为同步监视器。
同步方法、同步代码块的解锁,也是自动完成——只要程序离开synchronized修饰的代码块、方法,
此处的离开包括正常结束、因为异常退出,系统会自动释放对同步监视器的锁定。
c. 同步锁(JDK 1.5才有)
显式创建Lock、也会显式看到加锁、释放锁。
Lock是一个接口,该接口提供一个ReentrantLock(可重入锁)实现类。
做法:
(1)将显式锁定义成竞争资源的实例变量,并用final修饰(保证锁不会被替换)
务必保证:每个竞争资源有唯一的、不可替换的锁。
(2) 程序要修改竞争资源之前,先调用显式锁的lock方法执行锁定;
修改完成之后,在finally块中调用unlock方法释放锁定。