JUST DO IT


  • 首页

  • 归档

  • 分类

  • 标签

  • 关于

  • 搜索

Java并发总结-并发工具类

发表于 2019-10-12 | 分类于 Java并发

等待多线程完成的CountDownLatch

CountDownLatch允许一个或多个线程等待其他线程完成操作。

假如有这样一个需求:我们需要解析一个Excel里多个sheet的数据,此时可以考虑使用多线程,每个线程解析一个sheet里的数据,等到所有的sheet都解析完之后,程序需要提示解析完成。在这个需求中,要实现主线程等待所有线程完成sheet的解析操作,最简单的做法是使用join()方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class JoinCountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
Thread parser1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("parser1 finish");
}
});
Thread parser2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("parser2 finish");
}
});
parser1.start();
parser2.start();
parser1.join();
parser2.join();
System.out.println("all parser finish");
}
}
阅读全文 »

Java并发总结-原子操作类

发表于 2019-10-12 | 分类于 Java并发

Java从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。

因为变量的类型有很多种,所以在Atomic包里一共提供了13个类,属于4种类型的原子更新方式,分别是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性(字段)。Atomic包里的类基本都是使用Unsafe实现的包装类。

原子更新基本类型类

使用原子的方式更新基本类型,Atomic包提供了以下3个类:

  • AtomicBoolean:原子更新布尔类型。
  • AtomicInteger:原子更新整型。
  • AtomicLong:原子更新长整型。
阅读全文 »

Oracle归档日志启用与维护

发表于 2019-10-09 | 分类于 数据库

归档开启情况判断

  • 通用方法:

    1
    SQL> SELECT log_mode from v$database;
  • sys用户:

    1
    SQL> archive log list;

如何开启日志归档

  1. 启用归档日志前要先停止数据库

    1
    SQL> shutdown immediate;
  2. 开启数据库至mount状态(打开控制文件,不打开数据文件)

    1
    SQL> startup mount;
    阅读全文 »

Java并发总结-并发容器和框架

发表于 2019-09-29 | 分类于 Java并发

ConcurrentHashMap

ConcurrentHashMap是线程安全且高效的HashMap。

为什么使用它

在并发编程中使用HashMap可能导致程序死循环。而使用线程安全的HashTable效率又非常低下,基于以上两个原因,便有了ConcurrentHashMap的登场机会。

(1)线程不安全的HashMap

在多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。例如,执行以下代码会引起死循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
final HashMap<String, String> map = new HashMap<String, String>(2);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
map.put(UUID.randomUUID().toString(), "");
}
}, "ftf" + i).start();
}
}
}, "ftf");
t.start();
t.join();

HashMap在并发执行put操作时会引起死循环,是因为多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环获取Entry。

阅读全文 »

Java并发总结-锁

发表于 2019-09-20 | 分类于 Java并发

Lock接口

锁能够防止多个线程同时访问共享资源(但是有些锁可以允许多个线程并发的访问共享资源,比如读写锁)。

在Lock接口出现之前,Java程序是靠synchronized关键字实现锁功能的,而Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。

虽然它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。

使用synchronized关键字将会隐式地获取锁,但是它将锁的获取和释放固化了,也就是先获取再释放。当然,这种方式简化了同步的管理,可是扩展性没有显示的锁获取和释放来的好。

例如:手把手进行锁获取和释放,先获得锁A,然后再获取锁B,当锁B获得后,释放锁A同时获取锁C,当锁C获得后,再释放B同时获取锁D,以此类推。这种场景下,synchronized关键字就不那么容易实现了,而使用Lock却容易许多。

Lock的使用的方式:

1
2
3
4
5
6
7
8
9
Lock lock = new ReentrantLock();
lock.lock();
//不要将获取锁的过程写在try块中,因为如果在获取锁(自定义锁的实现)时发生了异常,异常抛出的同时,也会导致锁无故释放。
try {
//TODO
} finally {
//在finally块中释放锁,目的是保证在获取到锁之后,最终能够被释放。
lock.unlock();
}
阅读全文 »

Java并发总结-线程应用实例

发表于 2019-09-19 | 分类于 Java并发

等待超时模式

使用场景:调用一个方法时等待一段时间(一般来说是给定一个时间段),如果该方法能够在给定的时间段之内得到结果,那么将结果立刻返回,反之,超时返回默认结果。

前面的章节介绍了等待/通知的经典范式,即加锁、条件循环和处理逻辑3个步骤,而这种范式无法做到超时等待。而超时等待的加入,只需要对经典范式做出非常小的改动,改动内容如下所示:

假设超时时间段是T,那么可以推断出在当前时间now+T之后就会超时。

定义如下变量:

  • 等待持续时间:REMAINING=T。
  • 超时时间:FUTURE=now+T。

这时仅需要wait(REMAINING)即可,在wait(REMAINING)返回之后会将执行:REMAINING=FUTURE–now。如果REMAINING小于等于0,表示已经超时,直接退出,否则将继续执行wait(REMAINING)。

阅读全文 »

Java并发总结-线程间通信

发表于 2019-09-17 | 分类于 Java并发

常用关键字

volatile和synchronized

关键字volatile可以用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。但是不必过多使用volatile,因为它会降低程序执行的效率。

关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性。

如下使用了同步块和同步方法,通过使用javap工具查看生成的class文件信息来分析synchronized关键字的实现细节:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Synchronized {
public static void main(String[] args) {
// 对Synchronized Class对象进行加锁
synchronized (Synchronized.class) {
}
// 静态同步方法,对Synchronized Class对象进行加锁
m();
}

public static synchronized void m() {
// TODO
}
}
阅读全文 »

Java并发总结-线程基础

发表于 2019-09-15 | 分类于 Java并发

线程简介

多线程

一个Java程序的运行不仅仅是main()方法的运行,而是main线程和多个其他线程的同时运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MultiThread {
public static void main(String[] args) {
// 获取Java线程管理MXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// 不需要获取同步的monitor和synchronizer信息,仅获取线程和线程堆栈信息
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
// 遍历线程信息,仅打印线程ID和线程名称信息
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("[" + threadInfo.getThreadId() + "] "
+ threadInfo.getThreadName());
}
}
}
1
2
3
4
5
[5] Attach Listener //提供一种jvm进程间通信的能力,能让一个进程传命令给另外一个进程,并让它执行内部的一些操作
[4] Signal Dispatcher //分发处理发送给JVM信号的线程
[3] Finalizer //调用对象finalize方法的线程
[2] Reference Handler //清除Reference的线程
[1] main //main线程,用户程序入口
阅读全文 »
1…567…13
Try.Catch

Try.Catch

孤单而灿烂

102 日志
16 分类
26 标签
© 2017 — 2023 Try.Catch
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4
本站访客数 人次 本站总访问量 次
0%