1 怎麼知道一個端口號有沒有被佔用,被哪一個進程佔用。html
(1)windows下:(以3306爲例)mysql
netstat -ano | findstr 3306linux
LISTENING表示被佔用,4552表示佔用進程號,接下來查進程號。nginx
tasklist | finder 4552sql
很容易知道3306被mysql的mysqld進程佔用了。windows
(2)linux下:(以8082爲例)服務器
netstat -anp | grep 8082session
LISTEN表示端口被佔用,很明顯被nginx的進程佔用,進程號131763,能夠經過ps命令查看詳情:ps aux | grep 131763ide
2 簡單理解CountDownLatch和CyclicBarrier的做用this
(1)好比有一個線程A,它要等待其餘4個線程執行完畢以後才能執行,此時就能夠利用CountDownLatch來實現這種功能了。
簡單使用方法:構造對象的時候設置count 值(此例count=4),在A線程裏await一下將當前線程掛起,其餘4個線程完成特定功能後手動調用countDown方法,4次countDown後A線程繼續執行後面任務。
經典示例:在主線程中zookeeper構造會話以後,調用await(防止會話未建立就執行增刪該查的操做),服務器建立會話成功後回調Watcher的process方法,在該方法裏countDown。此時能夠主線程後續繼續操做。詳細看代碼:
public class ZKTest implements Watcher { private static CountDownLatch connectedSemaphore = new CountDownLatch(1); public static void main(String[] args) throws Exception { ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, new ZKTest()); System.out.println(zooKeeper.getState()); connectedSemaphore.await(); zooKeeper.create("/zk-test", "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); System.out.println("zooKeeper session established"); } @Override public void process(WatchedEvent watchedEvent) { System.out.println("receive WatchedEvent: " + watchedEvent); if (Event.KeeperState.SyncConnected == watchedEvent.getState()) { connectedSemaphore.countDown(); } } }
感受CountDownLatch和join很像啊,可是CountDownLatch更靈活,join必要要等到線程結束後才能處理後續代碼,而CountDownLatch是須要count減到0就好了。不清楚的能夠看博客瞭解細節https://www.jianshu.com/p/795151ac271b
(2)倘若有若干個線程都要進行操做A,而且只有全部線程都完成操做A以後,這些線程才能繼續作後面的事情,此時就能夠用CyclicBarrier。示例代碼以下:
public class CyclicBarrierTest { public static void main(String[] args) { int parties = 3; CyclicBarrier cyclicBarrier = new CyclicBarrier(parties); for (int i = 0; i < parties; i++) { MyTask myTask = new MyTask(cyclicBarrier); new Thread(myTask).start(); } } } class MyTask implements Runnable { private CyclicBarrier cyclicBarrier; public MyTask(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { try { System.out.println(Thread.currentThread().getName() + ":start A operation"); Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + ":end A operation"); cyclicBarrier.await(); System.out.println(Thread.currentThread().getName() + ":another operation"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }
輸出
Thread-0:start A operation Thread-2:start A operation Thread-1:start A operation Thread-1:end A operation Thread-2:end A operation Thread-0:end A operation Thread-2:another operation Thread-0:another operation Thread-1:another operation
關於這兩個更多細節請移步博客:http://www.javashuo.com/article/p-simfkhnj-b.html