java必學(xué)必會(huì)之線(xiàn)程(2)
一、線(xiàn)程的優(yōu)先級(jí)別

線(xiàn)程優(yōu)先級(jí)別的使用范例:
package cn.galc.test;
public class TestThread6 {
public static void main(String args[]) {
MyThread4 t4 = new MyThread4();
MyThread5 t5 = new MyThread5();
Thread t1 = new Thread(t4);
Thread t2 = new Thread(t5);
t1.setPriority(Thread.NORM_PRIORITY + 3);// 使用setPriority()方法設(shè)置線(xiàn)程的優(yōu)先級(jí)別,這里把t1線(xiàn)程的優(yōu)先級(jí)別進(jìn)行設(shè)置
/*
* 把線(xiàn)程t1的優(yōu)先級(jí)(priority)在正常優(yōu)先級(jí)(NORM_PRIORITY)的基礎(chǔ)上再提高3級(jí)
* 這樣t1的執(zhí)行一次的時(shí)間就會(huì)比t2的多很多
* 默認(rèn)情況下NORM_PRIORITY的值為5
*/
t1.start();
t2.start();
System.out.println("t1線(xiàn)程的優(yōu)先級(jí)是:" + t1.getPriority());
// 使用getPriority()方法取得線(xiàn)程的優(yōu)先級(jí)別,打印出t1的優(yōu)先級(jí)別為8
}
}
class MyThread4 implements Runnable {
public void run() {
for (int i = 0; i <= 1000; i++) {
System.out.println("T1:" + i);
}
}
}
class MyThread5 implements Runnable {
public void run() {
for (int i = 0; i <= 1000; i++) {
System.out.println("===============T2:" + i);
}
}
}
run()方法一結(jié)束,線(xiàn)程也就結(jié)束了。
二、線(xiàn)程同步
synchronized關(guān)鍵字的使用范例:
package cn.galc.test;
public class TestSync implements Runnable {
Timer timer = new Timer();
public static void main(String args[]) {
TestSync test = new TestSync();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.setName("t1");// 設(shè)置t1線(xiàn)程的名字
t2.setName("t2");// 設(shè)置t2線(xiàn)程的名字
t1.start();
t2.start();
}
public void run() {
timer.add(Thread.currentThread().getName());
}
}
class Timer {
private static int num = 0;
public/* synchronized */void add(String name) {// 在聲明方法時(shí)加入synchronized時(shí)表示在執(zhí)行這個(gè)方法的過(guò)程之中當(dāng)前對(duì)象被鎖定
synchronized (this) {
/*
* 使用synchronized(this)來(lái)鎖定當(dāng)前對(duì)象,這樣就不會(huì)再出現(xiàn)兩個(gè)不同的線(xiàn)程同時(shí)訪(fǎng)問(wèn)同一個(gè)對(duì)象資源的問(wèn)題了 只有當(dāng)一個(gè)線(xiàn)程訪(fǎng)問(wèn)結(jié)束后才會(huì)輪到下一個(gè)線(xiàn)程來(lái)訪(fǎng)問(wèn)
*/
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + ":你是第" + num + "個(gè)使用timer的線(xiàn)程");
}
}
}
線(xiàn)程死鎖的問(wèn)題:
package cn.galc.test;
/*這個(gè)小程序模擬的是線(xiàn)程死鎖的問(wèn)題*/
public class TestDeadLock implements Runnable {
public int flag = 1;
static Object o1 = new Object(), o2 = new Object();
public void run() {
System.out.println(Thread.currentThread().getName() + "的flag=" + flag);
/*
* 運(yùn)行程序后發(fā)現(xiàn)程序執(zhí)行到這里打印出flag以后就再也不往下執(zhí)行后面的if語(yǔ)句了
* 程序也就死在了這里,既不往下執(zhí)行也不退出
*/
/* 這是flag=1這個(gè)線(xiàn)程 */
if (flag == 1) {
synchronized (o1) {
/* 使用synchronized關(guān)鍵字把對(duì)象01鎖定了 */
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o2) {
/*
* 前面已經(jīng)鎖住了對(duì)象o1,只要再能鎖住o2,那么就能執(zhí)行打印出1的操作了
* 可是這里無(wú)法鎖定對(duì)象o2,因?yàn)樵诹硗庖粋€(gè)flag=0這個(gè)線(xiàn)程里面已經(jīng)把對(duì)象o1給鎖住了
* 盡管鎖住o2這個(gè)對(duì)象的線(xiàn)程會(huì)每隔500毫秒睡眠一次,可是在睡眠的時(shí)候仍然是鎖住o2不放的
*/
System.out.println("1");
}
}
}
/*
* 這里的兩個(gè)if語(yǔ)句都將無(wú)法執(zhí)行,因?yàn)橐呀?jīng)造成了線(xiàn)程死鎖的問(wèn)題
* flag=1這個(gè)線(xiàn)程在等待flag=0這個(gè)線(xiàn)程把對(duì)象o2的鎖解開(kāi),
* 而flag=0這個(gè)線(xiàn)程也在等待flag=1這個(gè)線(xiàn)程把對(duì)象o1的鎖解開(kāi)
* 然而這兩個(gè)線(xiàn)程都不愿意解開(kāi)鎖住的對(duì)象,所以就造成了線(xiàn)程死鎖的問(wèn)題
*/
/* 這是flag=0這個(gè)線(xiàn)程 */
if (flag == 0) {
synchronized (o2) {
/* 這里先使用synchronized鎖住對(duì)象o2 */
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o1) {
/*
* 前面已經(jīng)鎖住了對(duì)象o2,只要再能鎖住o1,那么就能執(zhí)行打印出0的操作了 可是這里無(wú)法鎖定對(duì)象o1,因?yàn)樵诹硗庖粋€(gè)flag=1這個(gè)線(xiàn)程里面已經(jīng)把對(duì)象o1給鎖住了 盡管鎖住o1這個(gè)對(duì)象的線(xiàn)程會(huì)每隔500毫秒睡眠一次,可是在睡眠的時(shí)候仍然是鎖住o1不放的
*/
System.out.println("0");
}
}
}
}
public static void main(String args[]) {
TestDeadLock td1 = new TestDeadLock();
TestDeadLock td2 = new TestDeadLock();
td1.flag = 1;
td2.flag = 0;
Thread t1 = new Thread(td1);
Thread t2 = new Thread(td2);
t1.setName("線(xiàn)程td1");
t2.setName("線(xiàn)程td2");
t1.start();
t2.start();
}
}
解決線(xiàn)程死鎖的問(wèn)題最好只鎖定一個(gè)對(duì)象,不要同時(shí)鎖定兩個(gè)對(duì)象
生產(chǎn)者消費(fèi)者問(wèn)題:
package cn.galc.test;
/* 范例名稱(chēng):生產(chǎn)者--消費(fèi)者問(wèn)題
* 源文件名稱(chēng):ProducerConsumer.java
* 要 點(diǎn):
* 1. 共享數(shù)據(jù)的不一致性/臨界資源的保護(hù)
* 2. Java對(duì)象鎖的概念
* 3. synchronized關(guān)鍵字/wait()及notify()方法
*/
public class ProducerConsumer {
public static void main(String args[]){
SyncStack stack = new SyncStack();
Runnable p=new Producer(stack);
Runnable c = new Consumer(stack);
Thread p1 = new Thread(p);
Thread c1 = new Thread(c);
p1.start();
c1.start();
}
}
class SyncStack{ //支持多線(xiàn)程同步操作的堆棧的實(shí)現(xiàn)
private int index = 0;
private char []data = new char[6];
public synchronized void push(char c){
if(index == data.length){
try{
this.wait();
}catch(InterruptedException e){}
}
this.notify();
data[index] = c;
index++;
}
public synchronized char pop(){
if(index ==0){
try{
this.wait();
}catch(InterruptedException e){}
}
this.notify();
index--;
return data[index];
}
}
class Producer implements Runnable{
SyncStack stack;
public Producer(SyncStack s){
stack = s;
}
public void run(){
for(int i=0; i<20; i++){
char c =(char)(Math.random()*26+'A');
stack.push(c);
System.out.println("produced:"+c);
try{
Thread.sleep((int)(Math.random()*1000));
}catch(InterruptedException e){
}
}
}
}
class Consumer implements Runnable{
SyncStack stack;
public Consumer(SyncStack s){
stack = s;
}
public void run(){
for(int i=0;i<20;i++){
char c = stack.pop();
System.out.println("消費(fèi):"+c);
try{
Thread.sleep((int)(Math.random()*1000));
}catch(InterruptedException e){
}
}
}
}
以上就是關(guān)于java線(xiàn)程的全部?jī)?nèi)容介紹,大家可以結(jié)合第一篇《java必學(xué)必會(huì)之線(xiàn)程(1)》進(jìn)行學(xué)習(xí),希望可以幫助到大家。
- java向多線(xiàn)程中傳遞參數(shù)的三種方法詳細(xì)介紹
- java 實(shí)現(xiàn)線(xiàn)程同步的方式有哪些
- JAVA中 終止線(xiàn)程的方法介紹
- Java多線(xiàn)程下載的實(shí)現(xiàn)方法
- Java多線(xiàn)程的用法詳解
- java線(xiàn)程之使用Runnable接口創(chuàng)建線(xiàn)程的方法
- Java線(xiàn)程關(guān)閉的3種方法
- java基本教程之Thread中start()和run()的區(qū)別 java多線(xiàn)程教程
- java基本教程之java線(xiàn)程等待與java喚醒線(xiàn)程 java多線(xiàn)程教程
相關(guān)文章
SpringBoot項(xiàng)目打包成jar后獲取classpath下文件失敗的解決
這篇文章主要介紹了SpringBoot項(xiàng)目打包成jar后獲取classpath下文件失敗的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Springboot訪(fǎng)問(wèn)templates html頁(yè)面過(guò)程詳解
這篇文章主要介紹了Springboot訪(fǎng)問(wèn)templates html頁(yè)面過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
Java的idea連接mongodb數(shù)據(jù)庫(kù)的詳細(xì)教程
這篇文章主要介紹了Java的idea連接mongodb數(shù)據(jù)庫(kù)的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
Java中使用增強(qiáng)for循環(huán)的實(shí)例方法
在本篇文章里小編給大家整理是的關(guān)于Java中如何使用增強(qiáng)for循環(huán)的實(shí)例內(nèi)容以及相關(guān)代碼,需要的朋友們可以學(xué)習(xí)下。2019-08-08
Java 線(xiàn)程池ThreadPoolExecutor源碼解析
這篇文章主要介紹了Java 線(xiàn)程池ThreadPoolExecutor源碼解析2022-03-03
關(guān)于Java集合框架Collection接口詳解
這篇文章主要介紹了關(guān)于Java集合框架Collection接口詳解,Collection接口是Java集合框架中的基礎(chǔ)接口,定義了一些基本的集合操作,包括添加元素、刪除元素、遍歷集合等,需要的朋友可以參考下2023-05-05
SpringCloud maven-assembly-plugin 多級(jí)目錄打包的實(shí)現(xiàn)
本文主要介紹了SpringCloud maven-assembly-plugin 多級(jí)目錄打包的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Java并發(fā)工具之Exchanger線(xiàn)程間交換數(shù)據(jù)詳解
這篇文章主要介紹了Java并發(fā)工具之Exchanger線(xiàn)程間交換數(shù)據(jù)詳解,Exchanger是一個(gè)用于線(xiàn)程間協(xié)作的工具類(lèi),Exchanger用于進(jìn)行線(xiàn)程間的數(shù)據(jù)交 換,它提供一個(gè)同步點(diǎn),在這個(gè)同步點(diǎn),兩個(gè)線(xiàn)程可以交換彼此的數(shù)據(jù),需要的朋友可以參考下2023-12-12
Spring解讀@Component和@Configuration的區(qū)別以及源碼分析
通過(guò)實(shí)例分析@Component和@Configuration注解的區(qū)別,核心在于@Configuration會(huì)通過(guò)CGLIB代理確保Bean的單例,而@Component不會(huì),在Spring容器中,使用@Configuration注解的類(lèi)會(huì)被CGLIB增強(qiáng),保證了即使在同一個(gè)類(lèi)中多次調(diào)用@Bean方法2024-10-10

