JAVA自學筆記23
1、多線程
1)引入:
2)進程
是正在運行的程序。是系統進行資源分配和調用的獨立單位。每一個進程都有它自己的內存空間和系統資源。
多進程:
單進程的計算機只能做一件事情,而現在的計算機都可以做多件事情。CPU在某個時間點上只能做一件事。每一個進程都有它自己的內存空間和系統資源。
3)多線程
-是進程中的單個順序控制流,是一條執行路徑
-一個進程如果只有一條執行路徑,則稱為單線程程序。一個進程如果有多條執行路徑,稱為多線程程序。
4)并行與并發
前者是邏輯上同時發生,指在某一個時間段內同時運行多個程序;后者是物理上同時發生,指在,某一個時間點內同時運行多個程序
5)Java程序運行原理
java命令會啟動java虛擬機,啟動jvm,等于啟動了一個應用程序,也就是啟動了一個進程,該進程會自動地啟動一個“主線程”,然后主線程去調用某個類的main方法,所以main方法運行在主線程中。在此之前的所有程序都是單線程的。
JVM的啟動時單線程還是多線程的呢?
多線程的。垃圾回收線程也要先啟動,否則很容易出現內容溢出。最少都啟動了兩個線程。
創建新執行線程有兩種方法,一種方法時將類聲明為Thread的子類。該子類應重寫Thread類的run方法。接下來可以分配并啟動該子類的實例。
即-自定義一個繼承自Thread的類
-重寫run()方法(不是類中的所有代碼都需要被線程執行。此時,為了區分哪些代碼能夠被執行。java提供了Thread類中的run()方法用于包含那些被執行的代碼。)
-創建對象
-啟動線程
另一種方法是聲明實現Runnable接口的類,該類然后實現run方法,然后就可以分配該類的實例。start()方法:使該線程開始執行,Java虛擬機調用該線程的run方法。它和run()的區別是run()僅僅是封裝被線程執行的代碼,直接調用的是普通方法start()首先啟動了線程,然后再由jvm去調用該線程的run()方法。
public class MyThread extends Thread{
public void run(){
for(
int x=
0;x<
10000;x++){
System.out.println(
"cc"+x);
}
}
}
public class MyThreadDemo{
public static void main (String[] args){
MyThread my1=
new MyThread();
MyThread my2=
new MyThread();
my1.start();
my2.start();
}
}
5)獲取和設置線程對象的名稱
獲取:
public final String getName(); //程序將輸出Thread-?,?按順序從0開始
設置
public final void setName(String name);
public class MyThread extends Thread{
public MyThread(){}
public MyThread(String name){
super(name);
}
public void run(){
for(
int x=
0;x<
10000;x++){
System.out.println(
"getName()+cc"+x);
}
}
}
MyThread my1=
new MyThread();
MyThread my2=
new MyThread();
my1.setName(
"cc");
my2.setName(
"dd");
my1.start();
my2.start();
}
}
MyThread my1=
new Mythread(
"許先生");
MyThread my1=
new Mythread(
"劉先生");
返回當前正在執行的線程對象
System.out.println(Thread currrentThread().getName());
6)線程調度
①分時調度模型:
所有線程輪流使用CPU的使用權,平均分配每個線程占用CPU的時間片
②搶占式調度模型 優先讓優先級高的線程使用CPU。如果線程的優先級相同,那么會隨機選擇一個,優先級高的線程獲取的CPU時間片相對多一些。Java使用此類模型
設置優先級的方法:
public final void setPriority (newPriority)
MAX_PRIORITY=10
MIN_PRIORITY=1
NORM_PRIORITY=5
獲取線程對象的優先級,默認優先級是5:
public final int getPriority()
public class ThreadPriority extends Thread{
public void run(){
for(
int x=
0;x<
10000;x++){
System.out.println(
"getName()+cc"+x);
}
}
}
public class ThreadPriorityDemo{
public static void main(String args[]){
ThreadPriority tp1=
new ThreadPriority();
ThreadPriority tp2=
new ThreadPriority();
ThreadPriority tp3=
new ThreadPriority();
tp1.setName(
"aa");
tp2.setName(
"bb");
tp3.setName(
"cc");tp1.getPriority();
tp2.getPriority();
tp3.getPriority()tp1.setPriorty(
8);tp1.start();
tp2.start();
tp3.start();
}
}
7)線程控制
線程休眠
public static void sleep(long mills)
在指定毫秒內讓當前正在執行的線程休眠
線程加入
public final void join()
等待該線程終止
public class ThreadJoin extends Thread{
public void run(){
for(
int x=
0;x<
10000;x++){
System.out.println(
"getName()+cc"+x);
}
}
}
public class ThreadJoinDemo{
public static void main(String args[]){
ThreadJoin tp1=
new ThreadJoin();
ThreadJoin tp2=
new ThreadJoin();
ThreadJoin tp3=
new ThreadJoin();
tp1.setName(
"aa");
tp2.setName(
"bb");
tp3.setName(
"cc");tp1.start();
tp1.join();
tp2.start();
tp3.start();
}
}
線程禮讓
public static void yield()
public class ThreadJoin extends Thread{
public void run(){
for(
int x=
0;x<
10000;x++){
System.out.println(
"getName()+cc"+x);
Thread.yield();
}
}
}
public class ThreadYieldDemo{
public static void main(String args[]){
ThreadYield tp1=
new ThreadYield();
ThreadYield tp2=
new ThreadYield();tp1.setName(
"aa");
tp2.setName(
"bb");tp1.start();
tp2.start();}
}
后臺線程
public final void setDaemon(boolean on)
將該線程標記為守護線程或用戶線程,當正在運行的線程都是守護線程時,jvm退出。必須在啟動線程前調用。
中斷線程
public final void stop()//已過時但仍可使用,具有不安全性
public void interrupt()//把線程狀態終止,并拋出InterruptedException 異常
public class ThreadStop extends Thread{
public void run(){
System.out.println(
"開始執行:"+
new Date());
}
}
public class ThreadStopDemo{
public static void main(String args[]){
ThreadStop ts=
new ThreadStop();
ts.start();
Thread.sleep(
3000);
ts.intereupt();
}
}
8)線程生命周期圖解:
9)多線程的實現方案2
①好處:可以避免由于java單繼承而帶來的局限性。適合多個相同程序的代碼去處理同一個資源的情況,把線程同程序的代碼,數據有效分離,較好地體現; 面向對象的設計思想。
-自定義類MyRunnable實現Runnable接口
-重寫run()方法
-創建MyRunnable類的對象
-創建Thread類的對象,作為上一步驟的參數傳遞
public class MyRunnable implements Runnable{
public void run(){
for(
int x=
0;x<
100){
System.out.println(Thread.currentThread.geiName()+
":"+x);
}
}
}
public class MyRunnableDemo{
public static void main(String args[]){
MyRunnable my=
new MyRunnable();
Thread t1=
new Thread(my);
Thread t2=
new Thread(my);
t1.setName(
"cc");
t1.setName(
"dd");
t1.start();
t2.start();
}
}
②兩種方式的比較圖解
@例題1:售賣電影票
public class SellTicketDemo{
public static void main(String args[]){
SellTicket st1=
new SelTicket();
SellTicket st2=
new SelTicket();
SellTicket st3=
new SelTicket();st1.setName(
"窗口1");
st2.setName(
"窗口2");
st3.setName(
"窗口3");st1.start();
st2.start();
st3.start();
}
}
public class SellTicket extends Thread{
public void run(){
private static int tickets=
100;
public void run(){
while(
true){
if(tickets>
0){
System.out.println(getName()+
"正在售出第"+(tickets--)+
"張票");
}
}
}
}
}
public class SellTickets implements Runnable{
private int tickets=
100;
public void run(){
while(
true){
if(tickets>
0){
System.out.println(getName()+
"正在售出第"+(tickets--)+
"張票");
}
}
}
}
public class void main(String args[]){
SellTicket st=
new SellTicket();Thread t1=
new Thread(st,
"窗口1");
Thread t2=
new Thread(st,
"窗口2");
Thread t1=
new Thread(st,
"窗口3");t1.start();
t2.start();
t3.start();
}
改進每次售出一張票延遲0.1秒
public class SellTickets implements Runnable{
private int tickets=
100;
private Object obj =
new Object();
public void run(){
synchronized(obj){
while(
true){
if(tickets>
0){
Thread.sleep(
1000);
System.out.println(getName()+
"正在售出第"+(tickets--)+
"張票");
}}
}
}
}
public class void main(String args[]){
SellTicket st=
new SellTicket();Thread t1=
new Thread(st,
"窗口1");
Thread t2=
new Thread(st,
"窗口2");
Thread t1=
new Thread(st,
"窗口3");t1.start();
t2.start();
t3.start();
}
出現了問題:
①相同號碼的票售出多次
②出現了負數序號的票
CPU的每一次執行必須是一個原子性(最簡單基本的)操作。是由于隨機性和延遲導致的
利用同步塊的方式解決上述問題
同步代碼塊:
格式:synchronized(對象)(需要同步的代碼;)
可以解決安全問題,其對象可以是任何對象。
把多條語句操作共享數據的部分給包起來
同步的好處與弊端:
好處:同步的出現解決了多線程的安全問題
弊端:當線程相當多時,因為每個線程都會去判斷同步上的鎖,非常耗費系統資源
前提:多個線程使用同一把鎖
同步方法:把同步關鍵字加載到方法上
A:同步代碼塊的鎖對象是誰呢?
* 任意對象。
*
* B:同步方法的格式及鎖對象問題?
* 把同步關鍵字加在方法上。
*
* 同步方法是誰呢?
* this
*
* C:靜態方法及鎖對象問題?
* 靜態方法的鎖對象是誰呢?
* 類的字節碼文件對象。(反射會講)
public class SellTicketDemo {public static void main(String[] args) {SellTicket st =
new SellTicket();Thread t1 =
new Thread(st,
"窗口1");Thread t2 =
new Thread(st,
"窗口2");Thread t3 =
new Thread(st,
"窗口3");t1.start();t2.start();t3.start();}
}
package cn.itcast_11;
public class SellTicket implements Runnable {private static int tickets =
100;
private Object obj =
new Object();
private Demo d =
new Demo();
private int x =
0;
@Overridepublic void run() {
while (
true) {
if(x%
2==
0){
synchronized (SellTicket.class) {
if (tickets >
0) {
try {Thread.sleep(
100);}
catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+
"正在出售第" + (tickets--) +
"張票 ");}}}
else {
private static synchronized void sellTicket() {
if (tickets >
0) {
try {Thread.sleep(
100);}
catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+
"正在出售第" + (tickets--) +
"張票 ");}
}
}
8)線程安全的類
StringBuffered
Vector
Hashtable
collections下有很多線程安全的類
轉載于:https://www.cnblogs.com/Tanqurey/p/10485332.html
總結
以上是生活随笔為你收集整理的JAVA自学笔记23的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。