- 什么是并發(fā)并行捅厂?
- 并發(fā):就是兩個或者多個事件在同一時刻上發(fā)生。
- 并行:就是兩個或者多個事件在同一時間段內(nèi)發(fā)生。
- 在java程序進程中至少包含兩條線程,一條主線程和一條垃圾回收線程较性。
- 在java程序中開啟線程的方式有兩種:
- 使用runtime類的exec方法:
Runtime runtime = Runtime.getRuntime(); runtime.exec("word");
- processBuilder 的start方法(1.5以后的,建議使用這個來開啟一個 新的進程)
ProcessBuilder pb = new ProcessBuilder("word"); pb.start();
- 創(chuàng)建多線程的形式:
- 通過繼承Thread類
class MusicThread extends java.lang.Thread {
@Override
public void run() {
for (int i = 0; i <500 ; i++) {
System.out.println("播放音樂"+i);
} } }
實現(xiàn)
for (int i = 0; i <50 ; i++) {
System.out.println("dayouxi"+i);
if (i == 10){
MusicThread ms = new MusicThread();
ms.start();
} }
- 通過實現(xiàn)Runnable接口來創(chuàng)建多線程
class MusImplementDemo implements java.lang.Runnable{
@Override public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("聽音樂"+i);
} } }
實現(xiàn)
for (int i = 0; i <50 ; i++) {
System.out.println("dayouxi"+i);
if (i == 10){
MusImplementDemo mui = new MusImplementDemo();
Thread th = new Thread(mui);
th.start();
} }
- 通過匿名內(nèi)部類創(chuàng)建:
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 50; j++) {
System.out.println("播放音樂"+i);
} } }).start();
- 繼承方式和實現(xiàn)方式的區(qū)別:
- 繼承方式:
- java中是單繼承,如果繼承了Thread該類就不能在繼承其他的類了赞咙。
- 從操作上分析责循,繼承方式更簡單,獲取線程名稱也簡單攀操。
- 從多線程共享一個資源的時候院仿,繼承不能做到。 - 接口實現(xiàn)方式:
- java中的類可以多實現(xiàn)接口(設(shè)計上更加優(yōu)雅)
- 從操作上比繼承稍微復(fù)雜一點崔赌,獲取線程的名字也稍微復(fù)雜一點意蛀,使用Thread類中的currentThread()方法。
- 從多線程共享一個資源的時候健芭,實現(xiàn)接口可以做到。
- 解決多線程并發(fā)訪問同一個資源的安全性問題: - 同步代碼塊 + java程序運行可使用任何對象作為作為同步監(jiān)聽的對象秀姐,但是一般我們把當(dāng)前并發(fā)的共同資源作為同步監(jiān)聽的對象慈迈。 * 注意在任何時候最多允許一個線程持有同步鎖,誰能拿到鎖誰就能執(zhí)行代碼塊內(nèi)部程序省有。
synchronized (this) {
if (num > 0) {
System.out.println(Thread.currentThread().getName() + "吃了" + num + "評估"); //模擬網(wǎng)絡(luò)延遲
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
}
- 同步方法:就是使用了synchronized修飾的方法
- 同步鎖是誰痒留?
- 對于非static方法同步鎖就是this。
- 對于static方法蠢沿,我們使用當(dāng)前方法所在的類的字節(jié)碼對象(AppleDemo2.class)
- 不要使用synchronized修飾run方法伸头,修飾后某個線程執(zhí)行完了所有功能,就像是多個線程出現(xiàn)串行舷蟀。
- 解決方案:把需要同步的操作代碼定義在一個新的方法中恤磷,并且該方法使用synchronized修飾,然后在run方法中調(diào)用這個方法野宜。
- 同步鎖是誰痒留?
class AppleDemo1 implements Runnable{
private int num = 500;
@Override
public void run() {
for (int i = 0; i < 500; i++) {
runThrea();
}
}
synchronized private void runThrea() {
if (num > 0){
System.out.println(Thread.currentThread().getName() + "吃了" + num + "評估");
//模擬網(wǎng)絡(luò)延遲
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
}
}
}
- 鎖機制
class AppleDemo3 implements Runnable{
//創(chuàng)建鎖 Lock lock = new ReentrantLock();
private int num = 500;
@Override
public void run() {
for (int i = 0; i < 500; i++) {
lockAdd();
}
}
private void lockAdd(){
//加鎖
lock.lock();
try {
if (num > 0) {
System.out.println(Thread.currentThread().getName() + "吃了" + num + "評估");
//模擬網(wǎng)絡(luò)延時
Thread.sleep(10);
num--;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//開鎖
lock.unlock();
}
}
}
7. synchronized的好與壞扫步? - 好處:保證了多線程并發(fā)訪問時的同步操作,避免線程的安全性問題匈子。 - 壞處: 使用了synchronzised的方法/代碼的性能比不用要低一些河胎。8. 對于線程通信要使用Lock機制就要使用Condition接口: - wait和notify方法只能被同步監(jiān)聽對象調(diào)用,但是Lock根本沒有了同步鎖機制虎敦,所以不能調(diào)用wait和notify方法游岳。 - 從java5開始 + 使用Lock機制取代Synchronized代碼塊和Synchronzied方法。 + 使用Condition接口對象的await其徙,signal方法來取代Object類中的wait胚迫,notify方法。