首先理解一下程序、進程、線程的具體解釋
程序(program):是爲完成特定任務、用某種語言編寫的一組指令的集合。即指一段靜態的代碼,靜態對象。
進程(process):是程序的一次執行過程,或是正在運行的一個程序。動態過程:有它自身的產生、存在和消亡的過程。
如:運行中的QQ,運行中的MP3播放器
程序是靜態的,進程是動態的
線程(thread):進程可進一步細化爲線程,是一個程序內部的一條執行路徑
若一個程序可同一時間執行多個線程,就是支持多線程的
廢話不多說;看看我看完視頻後寫的例子
創建線程的第一種方法
package com.ligang.com;
import javax.swing.text.StyledEditorKit.ForegroundAction;
/*
* 創建線程的第一種方法 繼承Thread類並重寫其中的run()方法
*/
public class ThreadTest {
public static void main(String[] args) {
new Thread(){//用內部內實現 重寫run()方法,求1-100的奇數和偶數
@Override
public void run() {
for(int i=0;i<=100;i++){
if(i%2==0){
System.out.println(Thread.currentThread().getName()+"::::"+i+"偶數");
}//currentThread():表示當前線程 getName():表示當前線程的名字
}
}
}.start();//最後調用start方法
new Thread(){
public void run() {
for(int i=0;i<=100;i++){
if(i%2!=0){
System.out.println(Thread.currentThread().getName()+"::::"+i+"奇數");
}
}
}
}.start();
}
}
創建線程的第二種方法並實現瞭如何控制同步進程的第二種方法
package com.ligang.com;
import java.text.BreakIterator;
/*
* 多線程的第二種方式,實現runnable接口
* 相比於繼承的方式實現多線程,runnable有可以多實現與共用同一個資源的優點
* 同步的第二種方式同步塊方法:public void synchronized +方法名{}
*/
class windows implements Runnable{//實現runnable接口
int x=100;//共享的數據
public void run() {//重寫run方法
while(true){
world();
}
}
public synchronized void world(){//設置進程代碼同步塊:這裏也會調用代碼監視器,
//只不過他是隱式的調用自己本身的對象作爲代碼監視器
if (x > 0) {
try {
Thread.currentThread().sleep(10);//讓他休息一下
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "還剩票數:" + x--);
}
}
}
public class RunnablTset {
public static void main(String[] args) {
windows w1=new windows();//只需要創建一次線程,接下來便可以多次調用
Thread t1=new Thread(w1);
Thread t2=new Thread(w1);
t1.setName("子線程2:");//設置線程的名字
t2.setName("子線程3:");
t1.start();
t2.start();
}
}
用synchronized的方式來實現代碼的同步
package com.ligang.com;
import java.text.BreakIterator;
/*
* 定義兩個線程實現兩個窗口同時賣票的模擬
* 用繼承方式實現的多線程控制其安全性
* 也是用synchronized的方式來實現代碼的同步,synchronized()中的代碼監視器不能用this了
* 因爲繼承的時候創建了三個對象,所以每次都會使用自己的代碼監視器,
* 從而沒有解決代碼同步的問題
*/
public class ThreadTest2 {
static int x=100;//假設有一百張票,讓兩個線程一起賣這一百張票,所以一定要把票數加static修飾
static Object obj=new Object();//定義一個類似於x似的靜態變量,用於代碼監視器
public static void main(String[] args) {
new Thread(){//在主函數中定義兩個內部類,實現兩個窗口的模擬
@Override
public void run() {//重寫run()方法
while(true){
synchronized (obj) {//用synchronized的方式來實現代碼的同步
if (x > 1) {
System.out.println(Thread.currentThread().getName() + "還剩票數:" + x--);//輸出所剩的票數
} else {
break;
}
}
}
}
}.start();//調用start()方法開啓線程
new Thread(){
@Override
public void run() {
while(true){
synchronized (obj) {//用synchronized的方式來實現代碼的同步
if (x > 0) {
System.out.println(Thread.currentThread().getName() + "還剩票數:" + x--);
} else {
break;
}
}
}
}
}.start();
}
}
來舉個小例子
package com.ligang.com;
import java.text.BreakIterator;
/*
* 銀行有一個賬戶。
* 有兩個儲戶分別向同一個賬戶存3000元,每次存1000,存3次。每次存完打印賬戶餘額。
*加上線程的通信,實現兩用戶交替向銀行卡里存錢
*wait();暫停進程使用
*notify()/notafyAll()喚醒進程
*
*/
public class Desposit implements Runnable {
double x = 0;
@Override
public void run() {
for (int i = 0; i < 3; i++) {
synchronized (this) {
notify();// 喚醒進程
x = x + 1000;
System.out.println("當前用戶:" + Thread.currentThread().getName() + "餘額爲:" + x);
try {
wait();// 等待一下 釋放cpu資源
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Desposit p = new Desposit();
Thread p1 = new Thread(p);
Thread p2 = new Thread(p);
p1.setName("客戶1");
p2.setName("客戶2");
p1.start();
p2.start();
}
}
生產者與消費者的經典例題
package com.ligang.com;
import javax.print.attribute.standard.NumberOfInterveningJobs;
import javax.sound.midi.VoiceStatus;
/*
* 生產者與消費者的經典例題
*/
class Clerk {
int product;
public synchronized void addProduct() {// 生產
if (product > 10) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
product++;
System.out.println(Thread.currentThread().getName()+"生產的第"+product+"個產品");
notify();
}
}
public synchronized void subProduct() {// 消費
if (product <0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName()+"消費的第"+product+"個產品");
product--;
notify();
}
}
}
class Produce implements Runnable {// 生產者生產
Clerk clerk;
public Produce(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println("生產者生產產品");
while (true) {
try {
Thread.currentThread();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.addProduct();
}
}
}
class Couser implements Runnable {// 消費者消費
Clerk clerk;
public Couser(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println("消費者消費產品");
while (true) {
try {
Thread.currentThread();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.subProduct();
}
}
}
public class ProductTest {
public static void main(String[] args) {
Clerk s=new Clerk();
Produce p1=new Produce(s);
Couser s1=new Couser(s);
Thread t1=new Thread(p1);
Thread t3=new Thread(p1);
Thread t4=new Thread(p1);
Thread t2=new Thread(s1);
t1.setName("生產者1:");
t3.setName("生產者2:");
t4.setName("生產者3:");
t2.setName("消費者:");
t1.start();
t2.start();
t3。start();
t4.start();
}
}
這篇博客中寫的文字很少,我想記得都寫在了代碼的註釋中了,總結起來還是很簡單的 線程的創建我寫了兩種方式,同步我也寫了兩個方式,後面寫了兩個作業題,把前面學的知識總結了一下,,菜鳥敬上,大神們,海涵