JAVA自學筆記24
1、能使用同步代碼塊就使用同步代碼塊,除非鎖對象是this,就可以考慮使用同步方法。靜態方法的鎖是類的字節碼對象。
2、JDK5新特性
1)接口Lock
void Lock()//獲取鎖
void unlock()//釋放鎖
ReentrantLock:實現類
public class SellTicketDemo{
public stsatic
void main(String args[]){
Thread t1=
new Thread(st,
"窗口1");
Thread t2=
new Thread(st,
"窗口2");
Thread t3=
new Thread(st,
"窗口3");t1.start();
t2.start();
t3.start();
}
}publlic class SellTicket implements Runnable{
private int tickets=
100;
private Lock
lock=
new ReentrantLock();
public void run(){
try{
lock.
lock();
if(tickets>
0){
try{
Thread.sleep(
100);
}
catch(InterruptedException e){
e.printStackTrace();
}
System.
out.println(Thread.currentThread().getName()+
"正在賣"+(tickets--)+
"張票")
})
finally{
lock.unlock();}
}
}
2)死鎖問題
①同步弊端:效率低,容易產生死鎖問題。如果出現了同步嵌套,就容易出現死鎖問題
②是指兩個或者兩個以上的線程在執行過程中,因爭奪資源產生的一種相互等待的現象。
public class MyLock{
public static final Object ObjA=
new Object();
public static final Object ObjB=
new Object();
}
public class DieLock extends Thread{
private boolean flag;
public DieLock(
boolean flag){
this.flag=flag;
public void run(){
if(flag){
Synchronized(MyLock.objA){
System.out.println(
"if objA");
Synchronized(MyLock.objB){
System.out.println(
"if objB");
}
}
}
else{
synchronized(MyLock.objB){
System.out.println(
"else objB");
Synchronized(MyLock.objA){
System.out.println(
"else objA");
}
}
}
}
}
public class DieDemo{
public static void main(String[] args){
DieLock dl1=
new DieLock(
true);
DieLock dl2=
new DieLock(
false);dl1.start();
dl2.start();
}
}
3)線程間的通信
不同種類的線程間針對同一個資源的操作,設置線程(生產者),獲取線程(消費者)
public class Student{
String name;
int age;
}
public class SetThread implements Runnable{
private Student s;
private int x=
0;
public SetThread(Student s){
this.s=s;
}
public void run(){
synchronized(s){
while(
true){
if(x%
2==
0){
s.name=
"cc";
s.age=
18;
}
else{
s.name=
"dd";
s.age=
13;
}
x++;
}
}
}}
public class GetThread implements Runnable{
implements Runnable{
private Student s;
public SetThread(Student s){
this.s=s;
}
public void run(){
synchronized(s){
while(
true){System,out,println(s.name);
}}}
}
public class StudentDemo{
Student s=
new Student{};
pubic
static void main {String args[]){
SetThread st=
new SetThread(s);
GetThread gt=
new GetThread(s);
Thread t1=
new Thread(st);
Thread t1=
new Thread(gt);
t1.start();
t2.start();
}
4)等待喚醒機制
圖解:
void wait();
在其他線程調用此對象的notify()或notifyAll()方法前,導致該線程等待
void notify()
喚醒在此對象監視器等待的單個線程
void notifyAll()
喚醒在此對象監視器等待的所有線程
public class Student{
String name;
int age;
boolean flag;
}
public class SetThread implements Runnable{
private Student s;
private int x=
0;
public SetThread(Student s){
this.s=s;
}
public void run(){
while(
true){
synchronized(s){
if(s.flag){
s.wait();}
if(x%
2==
0){
s.name=
"cc";
s.age=
18;
}
else{
s.name=
"dd";
s.age=
13;
}
x++;
s.flag=
true;
s.notify();
}
}
}}
public class GetThread implements Runnable{
implements Runnable{
private Student s;
public SetThread(Student s){
this.s=s;
}
public void run(){
synchronized(s){
if(!s.flag){
s.wait();
}
while(
true){
System,out,println(s.name);
s.flag=
false;
s.notify();
}}}
}
public class StudentDemo{
Student s=
new Student{};
pubic
static void main {String args[]){
SetThread st=
new SetThread(s);
GetThread gt=
new GetThread(s);
Thread t1=
new Thread(st);
Thread t1=
new Thread(gt);
t1.start();
t2.start();
}
線程的狀態轉換圖:
3、線程組
1)java使用ThreadGroup來表示線程組,它可以對一批線程進行分類管理,java允許程序直接對線程組進行控制
默認情況下,所有的線程都屬于主線程組
public final ThreadGroup getThreadGroup()
也可以給線程設置分組
Thread(ThreadGroup group,Runnable target,String name)
public class MyRunnable implements Runnable{
public void run(){
for(
int x=
0;x<
0;x++){
System.out.println(Thread.currentThread().getName()+
":"+x);
}
}
public class void ThreadGroupDemo{
public static void main(String args[]){
MyRunnable my=
new MyRunnable();
Thread t1=
new Thread(my,
"cc");
Thread t2=
new Thread(my,
"dd");ThreadGruop tg1=t1.getThreadGruop();
ThreadGruop tg2=t2.getThreadGruop();
String name1=tg1.getName();
String name2=tg2.getName();
method1();
}
}
private static void method1(){
ThreadGroup tg=
new ThreadGroup(
"這是新的組");MyRunnable my=
new MyRunnable();
Thread t1=
new Thread(tg,my,
"cc");
Thread t1=
new Thread(tg,my,
"dd");
}
//生產者消費者案例優化
public class Student{
private private String name;
int age;
private boolean flag;
public synchronized void set(String name,
int age){
if(
this.flag){
this.wait();
}
}
this.name=name;
this.age;
this.flag=
true;
this.notify();
}
public synchronized void get(){
if(!
this.flag){
this.wait();
}
}
System.out,println(
this.name);
this.flag=
false;
this.notify();
}
public class SetThread implements Runnable{
private Student s;
private int x=
0;
public SetThread(Student s){
this.s=s;
}
public void run(){
while(
true){
if(x%
2==
0){
s.set(
"cc",
23);
}
else{
s.set(
"dd",
23);
}
x++;
}
}
}}
public class GetThread implements Runnable{
implements Runnable{
private Student s;
public SetThread(Student s){
this.s=s;
}
public void run(){
synchronized(s){
if(!s.flag){
s.wait();
}
while(
true){
s.get();
}}}
}
public class StudentDemo{
Student s=
new Student{};
pubic
static void main {String args[]){
SetThread st=
new SetThread(s);
GetThread gt=
new GetThread(s);
Thread t1=
new Thread(st);
Thread t1=
new Thread(gt);
t1.start();
t2.start();
}
4、線程池
1)程序啟動一個新線程的成本是比較高的,因為它涉及到要與操作系統進行交互。而使用線程池可以很好地提高性能,尤其是當程序中要創建大量生存期很短的線程時,更應該考慮使用線程池。線程池里的每一個線程代碼結束后,并不會死亡,而是再次回到線程池中成為空閑狀態,等待下一個對象來使用。
在JDK5之前,必須手動實現自己的線程池,從JDK5開始,Java支持內置線程池。
JDK5新增了一個Exexutors工廠類來產生線程池,有如下幾個方法:
public static ExecutorsService newCacheThreadPool()
開啟具有緩存功能的線程池
public static ExecutorsService newFixedThreadPool(int nThreads)
創建指定個線程的線程池
public static ExecutorsService newSingleThreadExecutor()
創建1個線程池
這些方法的返回值是ExecutorsService對象。該對象表示一個線程池,可以執行Runnable對象或者Callable對象代表的線程。
public class ExecutorsDemo{
public static void main(String args[]){
ExecutorService pool=Executors.newFixedThreadPool(
2);
pool.submit(
new MyRunnable());
pool.submit(
new MyRunnable());
pool.shutdown();
}
}
public class MyRunnable implements Runnable{
public void run(){
for(
int x=
0;x<
100;x++){
System.out.println(Thread.currenThread().getName()+
":"+x);
}
}
}}
}
可以有返回值,可以做出異常,但代碼過于復雜一般不用
接口Callable
public class CallableDemo{
ExecutorService pool=Executors.newFixedThreadPool(
2);pool.submit(
new MyCallable());
pool.submit(
new MyCallable());
}
public class MyCallable implements Callable{
for(
int x=
0;x<
100;x++){
System.out.println(Thread.currenThread().getName()+
":"+x);}
public Object
call()
throws Exception{
return null;
}
}
5、匿名內部類實現多線程
new Thread(){代碼…}.start();
New Thread (new Runnable(){代碼…}}.start();
public class ThreadDemo{
public static void main(String args[]){
new Thread(){
public void run(){
for(
int x=
0;x<
100;x++){
System.
out.println(Thread.currenThread().getName()+
":"+x);
}
}
}.start();
new Thread(
new Runnable(){
public void run(){
for(
int x=
0;x<
100;x++){
System.
out.println(Thread.currenThread().getName()+
":"+x);
}
}
}).start();
}
new Thread(
new Runnable(){
public void run(){
for(
int x=
0;x<
100;x++){
System.
out.println(
"Hello"+
":"+x);
}
}
}){
public void run(){
for(
int x=
0;x<
100;x++){
System.
out.println(
"World"+
":"+x);
}
}
}.start();
}
}
6、定時器
1)定時器是一個應用十分廣泛的線程工具,可用于調度多個定時任務以后線程的方式執行,在java中,可以通過Timer和TimerTask類來實現定義調度的功能
2)Timer
public Timer()
//創建一個新的計時器
public void schedule(TimerTask task,long delay)
安排在指定延遲后執行指定的任務
public void schedule(TimerTask task,long period)
安排指定的任務從指定的延遲后開始進行重復的固定延遲執行
3)TimerTask
public abstract void run()
此計時器任務要執行的操作
public boolean cancel()
//終止此計時器,丟棄所有當前已安排的任務
public class TimerDemo{
public static void main(String args[]){
Timer t=
new Timer();
t.schedule(
new MyTask(t),
3000);
}
}
class MyTask extends TimerTask{
private Timer t;
public MyTask(){}
public MyTask(Timer t){
this.t=t;
}
public void run(){
System.out.println(
"爆炸");
t.cancel();
}
}
class DeleteFolder extends TimerTask{
public void run(){
File file=
new File(
"demo");
deleteFolder(srcFolder);
}
public void deleteFolder(File srcFolder){
File[] fileArray=srcFolder.listFiles();
if(fileArray!=
null){
for(File file:fileArray){
if(file.isDirectory()){
deleteFolder(file);
}
else{
file.delete();
}
}
srcFolder.delete();
}
}
}
public class TimerTest{
public static void main(String args[]){
Timer t=
new Timer();
String s=
"2018-8-23 15:52:24";
SimpleDateFormat sdf =
new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
Date d=sdf.parse(s);t.schdule(
new DeleteFolder(),d);
}
}
7、多線程常見面試題回顧
1)多線程有幾種實現方案,分別是哪幾種。
兩(三)種。繼承Thread類,實現Runnable接口,(實現Callable接口)
2)同步有幾種方式,分別是什么?
同步代碼塊
同步方法
3)
8、面向對象思想設計原則及常見設計模式
1)面向對象思想設計原則
2)設計模式
設計模式是一套被反復使用,多數人知曉的,經過分類編目的代碼設計經驗總結。使用設計模式是為了可重用代碼,讓代碼更容易被他人理解,保證代碼的可靠性。
轉載于:https://www.cnblogs.com/Tanqurey/p/10485333.html
總結
以上是生活随笔為你收集整理的JAVA自学笔记24的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。