JavaScript實現移動端簽字功能
阿新 • • 發佈:2021-10-18
程式、程序、執行緒
- 程式(program):靜態程式碼
- 程序(process):程式的一次執行過程,或是一個正在執行中的程式
- 執行緒(thread):程序可以進一步細化為執行緒,是一個程式內部的一條執行路徑
建立執行緒的4種方式
繼承Thread類
public class ThreadTest { public static void main(String[] args) { new EvenPrinter().start(); new EvenPrinter().start(); } } /** * 列印100以內的偶數 */ class EvenPrinter extends Thread { @Override public void run() { for (int i = 1; i <= 100; i++) { if (i % 2 == 0) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } }
實現Runnable介面
public class ThreadTest { public static void main(String[] args) { OddPrinter oddPrinter = new OddPrinter(); new Thread(oddPrinter).start(); new Thread(oddPrinter).start(); new Thread(oddPrinter).start(); } } /** * 列印100以內的奇數 */ class OddPrinter implements Runnable { @Override public void run() { for (int i = 1; i <= 100; i++) { if (i % 2 != 0) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } }
實現Callable介面
與實現Runnable介面相比,實現Callable這種方式:
- 可以接收返回值
- 支援泛型
- 可丟擲異常
public class ThreadTest { public static void main(String[] args) { NumberPrinter numberPrinter = new NumberPrinter(); FutureTask<Integer> task = new FutureTask<>(numberPrinter); new Thread(task).start(); Integer sum = null; try { sum = task.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("sum=" + sum); } } /** * 列印100以內的數字,並返回其和 */ class NumberPrinter implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for (int i = 1; i <= 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); sum += i; } return sum; } }
使用執行緒池
public class ThreadTest {
public static void main(String[] args) {
// 建立一個包含10個執行緒的執行緒池
ExecutorService service = Executors.newFixedThreadPool(10);
// void execute(Runnable command)
service.execute(new OddPrinter());
service.execute(new EvenPrinter());
// <T> Future<T> submit(Callable<T> task)
Future<Integer> future = service.submit(new NumberPrinter());
Integer sum = 0;
try {
sum = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("sum=" + sum);
// 關閉執行緒池
service.shutdown();
}
}
/**
* 列印100以內的數字,並返回其和
*/
class NumberPrinter implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
sum += i;
}
return sum;
}
}
/**
* 列印100以內的奇數
*/
class OddPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
/**
* 列印100以內的偶數
*/
class EvenPrinter extends Thread {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
Thread類常用方法
- void start():啟動執行緒,執行run()方法
- void run():執行緒在被排程時執行的操作
- String getName()
- void setName(String name)
- static Thread currentThread():返回當前執行緒
- static void yeid():執行緒讓步,把執行機會讓給其他執行緒
- void join():線上程a中呼叫執行緒b的join()方法,等執行緒b執行完畢後,繼續執行執行緒a
- static void sleep(long millis):讓當前執行緒休眠指定的毫秒數
- boolean isAlive():執行緒是否存活
public class ThreadTest {
public static void main(String[] args) {
OddPrinter oddPrinter = new OddPrinter();
Thread t1 = new Thread(oddPrinter);
// 設定執行緒名稱
t1.setName("執行緒t1");
// 啟動執行緒t1
t1.start();
// 等待執行緒t1執行完畢後,再繼續執行後面的程式碼
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 執行緒的狀態(生命週期)
System.out.println("t1.getState():" + t1.getState());
// 執行緒是否存活
System.out.println("t1.isAlive():" + t1.isAlive());
}
}
/**
* 列印100以內的奇數
*/
class OddPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0) {
// 讓當前執行緒休眠100毫秒
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
執行緒的生命週期
執行緒同步
使用synchronized程式碼塊解決Runnable介面實現類的執行緒安全問題
public class TicketWindowTest {
public static void main(String[] args) {
TicketWindow ticketWindow = new TicketWindow();
new Thread(ticketWindow, "視窗1").start();
new Thread(ticketWindow, "視窗2").start();
new Thread(ticketWindow, "視窗3").start();
}
}
/**
* 售票視窗
*/
class TicketWindow implements Runnable {
// 總共100張票
private int ticket = 100;
@Override
public void run() {
while (true) {
// 使用this作為同步監視器(鎖)
synchronized (this) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
}
使用synchronized程式碼塊解決Thread子類的執行緒安全問題
public class TicketWindowTest {
public static void main(String[] args) {
new TicketWindow().start();
new TicketWindow().start();
new TicketWindow().start();
}
}
/**
* 售票視窗
*/
class TicketWindow extends Thread {
// 總共100張票
private static int ticket = 100;
@Override
public void run() {
while (true) {
// 使用TicketWindow.class作為同步監視器(鎖)
synchronized (TicketWindow.class) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
}
使用synchronized方法解決Runnable介面實現類的執行緒安全問題
public class TicketWindowTest {
public static void main(String[] args) {
TicketWindow ticketWindow = new TicketWindow();
new Thread(ticketWindow, "視窗1").start();
new Thread(ticketWindow, "視窗2").start();
new Thread(ticketWindow, "視窗3").start();
}
}
/**
* 售票視窗
*/
class TicketWindow implements Runnable {
// 總共100張票
private int ticket = 100;
@Override
public void run() {
while (ticket > 0) {
sale();
}
}
/**
* sale方法不是靜態的,將使用this作為同步監視器
*/
private synchronized void sale() {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
}
}
使用synchronized方法解決Thread子類的執行緒安全問題
public class TicketWindowTest {
public static void main(String[] args) {
new TicketWindow().start();
new TicketWindow().start();
new TicketWindow().start();
}
}
/**
* 售票視窗
*/
class TicketWindow extends Thread {
// 總共100張票
private static int ticket = 100;
@Override
public void run() {
while (ticket > 0) {
sale();
}
}
/**
* sale方法是靜態的,將使用TicketWindow.class作為同步監視器
*/
private static synchronized void sale() {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
}
}
使用Lock介面手動開關鎖
public class TicketWindowTest {
public static void main(String[] args) {
TicketWindow ticketWindow = new TicketWindow();
new Thread(ticketWindow, "視窗1").start();
new Thread(ticketWindow, "視窗2").start();
new Thread(ticketWindow, "視窗3").start();
}
}
/**
* 售票視窗
*/
class TicketWindow implements Runnable {
// 總共100張票
private int ticket = 100;
// 同步監視器
private ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
while (ticket > 0) {
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
lock.unlock();
}
}
}
執行緒通訊
三個方法:
- wait(): 令當前執行緒掛起並放棄CPU、同步資源並等待,使別的執行緒可訪問並修改共享資源
- notify():喚醒正在排隊等待同步資源的執行緒中優先順序最高者結束等待
- notifyAll():喚醒正在排隊等待資源的所有執行緒結束等待
注意點:
- 以上三個方法宣告在Object類中
- 以上三個方法只能在在synchronized方法或synchronized程式碼塊中才能使用
public class CommTest {
public static void main(String[] args) {
// 兩個執行緒將交替列印
NumberPrinter numberPrinter = new NumberPrinter();
new Thread(numberPrinter).start();
new Thread(numberPrinter).start();
}
}
/**
* 列印1~100
*/
class NumberPrinter implements Runnable {
private int i = 1;
@Override
public void run() {
while (true) {
synchronized (this) {
if (i <= 100) {
// 喚醒一個執行緒
notify();
System.out.println(Thread.currentThread().getName() + ":" + i++);
// 休眠當前執行緒
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 喚醒所有執行緒,否則程式無法自動退出
notifyAll();
break;
}
}
}
}
}