序文
クラスとテーブルロック、オンラインの杭については、この私はもっと言うことはありません。
コンテンツを宣伝しないように、かなりされていないため。
記事:ロックオンでJava:同期、再入国ロック、書き込みロック -ジェーンの本
https://www.jianshu.com/p/21e095b71373
6つの状態をスレッド(ソースThreadクラスがenum状態を持っています)
1. 初期(NEW) :新しいスレッドオブジェクトを作成しますが、start()メソッドが呼び出されていません。
2. ファイル名を指定して実行(RUNNABLE):Javaスレッドは、一般的と呼ばれる2つの状態(実行中)(準備)して実行可能な状態になります「実行」。
スレッドオブジェクトを作成した後、(例えばメインスレッドのような)他のスレッドは、オブジェクトのstart()メソッドを呼び出します。スレッドの状態は、CPUを使用する権利、レディ状態(レディ)で、この時間を取得し、スレッドのスケジューリングを選択されるのを待って、プール内の実行可能スレッドに位置しています。スレッドCPUタイムスライスを取得した後レディ状態が動作状態(実行中)になります。
3. 遮断(ブロック):スレッドがロックでブロックされることを意味します。
4. 待ち(WAITING) :この状態は入力されたスレッドは、他のスレッドがいくつかの特定のアクション(通知や割り込みを)作るのを待つ必要があります。タイムアウト時間(TIMED_WAITING) :この状態は異なって待っている、それが指定した時間後に自分自身を返すことができます。
6. 終了(TERMINATED) :スレッドが終了しました。
簡単には、あなたは元の状態にはない1対1の対応が、図を参照することができ、理解します。
状態のスポット機能の効果
- 1.収率()メソッドは、翻訳されたスレッドの譲歩。名前が示唆した後、スレッドは、このメソッドを使用するとき、それはアウトできるようにCPUの実行時間を所有することを、自分自身や他のスレッドが実行してみましょう、自分自身に注意を払うにあるか、他のスレッドではない、単に他のスレッドを与えるために、実行しています。 私は行きたくない、バスのレースの全員を許可する:たとえば:彼は突然言ったときに、バス上のキューにある友人のグループは、収量に向けます。その後、バスで駆けつけた誰もが、バスに乗って、バス上に収量があるかもしれない他の人があるかもしれません。
- Thread.sleep(長いミリ秒)は、現在のスレッドがこの方法、TIMED_WAITING状態に現在のスレッドを呼び出す必要がありますが、レディ状態にミリスレッド後のオブジェクトのロック、自動ウェイクアップを解放しません。役割:他のスレッドを実行する機会を与えるための最良の方法。
- t.join()/ t.join(長いミリ秒)、現在のメソッド呼び出しをスレッドが他のスレッドtに参加し、WAITING / TIMED_WAITING状態に現在のスレッドが現在のスレッドがすでにオブジェクトのロックを保持して解放しません。スレッドTは、準備完了状態に現在のスレッドに終了したか、ミリ秒の時間。
- obj.wait()、現在のスレッドが待機キューに、オブジェクトロックオブジェクトの待機()メソッドは、現在のスレッドのリリースを呼び出します。通知頼る()/のnotifyAll()が自動的に起こすためにタイムアウト時間をウェイクまたは待機(長いタイムアウト)。
- obj.notify()選択は任意であり、このオブジェクトのモニターで待機中のスレッドを1つ目を覚まします。notifyAll()このオブジェクトのモニターで待機中のすべてのスレッドをウェイクアップします。
1.ReenTranLock和同期
使用シナリオは:複雑ではない場合は下の自動最適化をsynchroizedので一般的には、提案されている業務用は、同期、および例外ではありませんが、ロックがコードにブロックされる再入可能ロック・スレッドを解放書き込みが発生した場合には、ロック自動異常解除をサポートしています。しかし、もし、複雑なビジネス(例えば、マルチスレッド1は、この厄介なビジネスを覚ますでしょう、しばらくの間停止しなければならないための一つに記載)、唯一のコードサイズを十分に把握ではない同期使用して、再入可能ロック文言よりプロセス指向に傾いて、より優れた制御ロジックのため、再入可能ロックもちろん、このシステム、これは余談で、定義によってそれはリエントラントロックされ、他の多くの機能があります。
2.synchronized(物体)
このオブジェクトは、それを決定するものに基づいているかどうか?これにミーンズプラス同期オブジェクトのデフォルトの一般的な、それはクラスを指します。したがって、このクラスでロックされている場合、オブジェクト全体がロックされている場合、ロックは、同じ使用し、その範囲を持っているので、間違って行くが、パフォーマンスは依然として最適ではないかもしれないことができ、共有変数に一般的には、マルチスレッドプログラミングでロックを取得する唯一つのスレッドの実行権時間で同じコードブロック内の同期(オブジェクト)が、ロックは待機します対象ブロックの他のスレッドをロックされています。
例えば、スレッドセーフと異なるのConcurrentHashMapは、(それだけで、簡単な暴力に比較パフォーマンスを同期フィールドを追加)ハッシュテーブルを推奨されていません、ConcurrentHashMapのは、直接配列を初期化しない場合はロックされますが、コンペア・アンド・スワップの使用CAS操作、及びリスト・ノード・ノード、同期(現在のノードnode)のアレイに添加したとき、範囲単に同期ロック現在のノードので、どのような利点が達成され、図を参照してください。
1.単純な力がデータノードにオブジェクトロック操作に適用されるが、アレイ全体がロックされているハッシュマップように、追加され、性能が良好ではありません
2.(現在のノードのノード)同期データアレイは、それがブロックされない場合、その後、ハッシュマップの他のノードへのビット。このため、アクションと書き込み汚れたデータの発生しない、より合理的と優れたパフォーマンスを実現そう。
ThreadPoolExecutorについて
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1,1,0,TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(100),new ThreadPoolExecutor.DiscardOldestPolicy());
4点のThreadPoolExecutorコア、再び強調する。
1、タスクが提出される場合、(コアスレッドがアイドル状態であっても)タスクを実行するためにコアスレッドを作成します。
図2に示すように、コアがスレッドcorePoolSizeの数に達したときに、キュー後続BlockingQueueのに提出されます。
フルBlockingQueueのは、(オファーが失敗した)、それは(スレッドは一時的に、破壊される、特定の時刻よりもアイドル)一時的なスレッドを作成します。3、。
スレッドの合計数がmaximumPoolSize、フォローアップの提出タスクが拒否されるのRejectedExecutionHandlerに達する4、
ロックの使用
/**
* @ClassName FirstController
* @Description 测试
* gain: 这个案例故意写得不规范,总结一些问题,
* 1.调用Condition.await()/singnal() 的时候,当前线程需要获得锁
* 2.await()调用后,当前线程释放锁。但死锁的形成原因一般为: 双方都调用await()后等待,没有线程跑下去。
* 3.业务复杂一般倾向用ReentrantLock,但synchronized(String)使用也很简易,、
* 4.String.intern()方法会从字符池拿变量,所以"1".equals(new String("1").intern())结果为true
* 5.tryLock(); 多线程里防止重复执行的内容,例如重复提交等,一般在if()内使用
//根据尝试获取锁的值来判断具体执行的代码
if(lock.tryLock(long time , TimeUnit unit)) {
try{
//处理任务
}catch(Exception ex){
}finally{
//当获取锁成功时最后一定要记住finally去关闭锁
lock.unlock(); //释放锁
}
}else {
//else时为未获取锁,则无需去关闭锁
//如果不能获取锁,则直接做其他事情
}
*
* @Author lkun
**/
@ApiIgnore
@RestController
public class FirstController {
int bSize = 500;
private final static Logger logger = LoggerFactory.getLogger(FirstController.class);
private ExecutorService threadPool;
private Lock lock = new ReentrantLock();
private final Condition firstB = lock.newCondition();
final AtomicInteger atoInt = new AtomicInteger();
{
//threadPool = Executors.newSingleThreadExecutor();
threadPool = new ThreadPoolExecutor(2, 50, 100,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(300),new ThreadPoolExecutor.CallerRunsPolicy());
}
@Autowired
IrisDataService irisDataService;
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
IrisDataRepository irisDataRepository;
@RequestMapping(value = "/helloWorld",method = RequestMethod.GET)
public String helloWorld() throws Exception {
atoInt.set(bSize);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
final int num = i;
lock.lock();
try {
if (atoInt.get() > 0) {
firstB.await();
}
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("run thread A: " + num);
}catch(Exception e) {
logger.error("异常A");
}
}
});
} catch (Exception e) {
logger.error("error thread:" + e.getMessage(), e);
}finally {
lock.unlock();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < bSize; i++) {
final int num = i;
threadPool.execute(new Runnable(){
@Override
public void run(){
try {
Thread.sleep(1000);
System.out.println("run thread B: " + num);
if(atoInt.addAndGet(-1) <= 0) {
//sinal()前提是需要获取锁,但这里想让并发处理尽可能高性能,所以建议把lock()住的代码块尽量简短
lock.lock();
firstB.signal();
lock.unlock();
};
}catch(Exception e){
logger.error("error thread:" + e.getMessage(),e);
}
}
});
}
}
}).start();
for(int i = 0 ; i < 1000; i++) {
System.out.println("main Thread run" + i);
}
return "true";
}
@RequestMapping(value = "/testMethod",method = RequestMethod.GET)
public String testMethod() {
new Thread(new Runnable(){
@Override
public void run() {
synA();
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
synB();
}
}).start();
return "test success11ger";
}
private void synA() {
synchronized("1") {
for(int i = 0 ; i < 1000; i++) {
try {
Thread.sleep(600);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A run :" + i);
}
}
}
private void synB() {
synchronized(new String("1").intern()) {
for(int i = 0 ; i < 1000; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B run :" + i);
}
}
}
}
2.CountDownLatch(統計的結果を得るために、このような同時)
//この例では、問題を抱えている、あまりにも多くのスレッドは現実的ではない、作成します
public ResultMes republishByDatabase(final String sn) throws Exception {
logger.info("开始重发人员数据,sn=" + sn);
//获取流程成功下发人员记录
List mapList = jdbcTemplate.queryForList("select t2.id_number,t2.status from iotmgr_device t1,dr_authorized_detail t2 " +
"where t1.device_code = t2.device_code and t1.brand = 'IK' and t1.parameter_id = ? and t1.delete_type = '0' and t2.status in('1','2')",new Object[]{sn});
int leng = mapList.size();
final StringBuffer logBuilder = new StringBuffer();
final AtomicInteger failCounter = new AtomicInteger();
Thread[] threads = new Thread[leng];
final CountDownLatch latch = new CountDownLatch(leng);
final Lock lock = new ReentrantLock();
//全部下发后,统计下发结果
new Thread(new Runnable() {
@Override
public void run() {
try {
latch.await();
logger.info("重发人员数据结束,sn=" + sn);
if(logBuilder.length() > 0) {
logger.error(logBuilder.toString());
logger.error("重发失败数目=" + failCounter.get());
}else {
logger.info("重发人员数据全部成功!");
}
}catch(Exception e) {
logger.error("重发countDownLatch异常" + e.getMessage());
}
}
}).start();
for(int i = 0; i < leng; i++) {
final Map map = (Map)mapList.get(i);
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
ResultMes resMessage = null;
String idNumber = null;
Integer sendCardNumber = 1; //是否下发卡号
try {
lock.lock();
String status = (String)map.get("status"); //授权状态
idNumber = (String)map.get("id_number"); //身份证
if("1".equals(status)) { //正常使用
sendCardNumber = 1;
}else if("2".equals(status)) { //挂失卡
sendCardNumber = 0;
}else if("3".equals(status)) { //失效
return;
}
resMessage = addIrisBusiness(sn,idNumber,0,sendCardNumber); //下发人员数据
}catch(Exception e) {
failCounter.incrementAndGet();
latch.countDown();
lock.unlock();
//防止数据不完整会导致异常中断操作。这里仅对异常捕捉打印日志
logBuilder.append("下发失败idNumber=" + idNumber + e.getMessage() + "\r\n");
return;
}
if(!resMessage.isSuccess()) {
failCounter.incrementAndGet();
logBuilder.append("下发失败idNumber=" + idNumber + resMessage.getMessage() + "\r\n");
}
latch.countDown();
lock.unlock();
}
});
threads[i].start();
}
return ResultMes.buildSuccess();
}