1. 程式人生 > 程式設計 >JavaScript實現移動端簽字功能

JavaScript實現移動端簽字功能

程式、程序、執行緒

  • 程式(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;
                }
            }
        }
    }
}