Thread类的run方法和start方法
- public class PrintThread extends Thread {
- private String msg;
- public PrintThread(String msg) {
- this.msg = msg;
- }
- public void run() {
- for(int i = 0; i < 10000; i++) {
- System.out.print(msg);
- }
- }
- public static void main(String[] args {
- new PrintThread("Good!").start();
- new PrintThread("Nice!").start();
- }
- }
public interface Runnable {public abstract void run();}已实现Runnable接口的类必须实现run()方法。
- public class PrintThread implements Runnable {
- private String msg;
- public PrintThread(String msg) {
- this.msg = msg;
- }
- public void run() {
- for(int i = 0; i < 10000; i++) {
- System.out.print(msg);
- }
- }
- public static void main(String[] args {
- new Thread(new PrintThread("Good!")).start();
- new Thread(new PrintThread("Nice!")).start();
- }
- }
线程的暂时停在
线程的共享互斥
线程的协调
Single Threaded Execution Pattern
使用该模式来限制同时只让一个线程运行。先看一个不是使用该模式的多线程的例子,并非线程安全(Thread-safe)的Gate类:
- public class Main {
- public static void main(String[] args) {
- System.out.println("Testing Gate, hit CTRC+C to exit.");
- Gate gate = new Gate();
- new UserThread(gate, "Alice", "Alaska").start();
- new UserThread(gate, "Bobby", "Brazil").start();
- new UserThread(gate, "Chris", "Canada").start();
- }
- }
- public class Gate {
- private int counter = 0;
- private String name = "Nobody";
- private String address = "Nowhere";
- public void pass(String name, String address) {
- this.counter++;
- this.name = name;
- this.address = address;
- check();
- }
- public String toString() {
- return "No. " + counter + " name: " + name + ", address: " + address;
- }
- private void check() {
- if (name.charAt(0) != address.charAt(0)) {
- System.out.println("******BROKEN*******" + toString());
- }
- }
- public class UserThread extends Thread {
- private final Gate gate;
- private final String myname;
- private final String myaddress;
- public UserThread (Gate gate, String myname, String myaddress) {
- this.gate = gate;
- this.myname = myname;
- this.myaddress =myaddress;
- }
- public void run() {
- System.out.println(this.myname + "Begin");
- while(true) {
- gate.pass(this.myname,myaddress);
- }
- }
- }
- }
执行看看。
由于Gate类不是线程安全的,当多个线程对其的状态进行更改时,会出现与期望不符的结果。可以通过将Gate类改造成线程安全的类来解决这个问题。线程安全最简单的方法即是使用本模式,使同一时间只让一个线程执行。线程安全版的Gate类如下:
- public class Gate {
- private int counter = 0;
- private String name = "Nobody";
- private String address = "Nowhere";
- public synchronized void pass(String name, String address) {
- this.counter++;
- this.name = name;
- this.address = address;
- check();
- }
- public synchronized String toString() {
- return "No. " + counter + " name: " + name + ", address: " + address;
- }
- private void check() {
- if (name.charAt(0) != address.charAt(0)) {
- System.out.println("******BROKEN*******" + toString());
- }
- }
- }
即在pass()方法和toString()方法前面加上synchronized关键字,这样Gate类就是线程安全的类了。synchronized锁扮演的角色就是对共享资源的保护。
Single Threaded Execution Pattern的参与者:
SharedResource(共享资源):在本例中Gate类(准确说是Gate类的实例)是这个SharedResource。 SharedResource是可由多个线程访问的类。在该模式下,我们对unsafeMethod加以防护,限制同时只能有一个线程进行访问,在 Java语言中,将unsafeMethod定义成synchronized方法,就可以实现这个目标。这个必须只让单线程执行的程序范围,我们称为临界 区(critical section)
何时该适用Single Threaded Execution Pattern,当SharedResouce实例可能同时被多个线程访问的时候,并且SharedResource的状态可能变化的时候。
另外注意,使用Single Threaded Execution Pattern 时可能会发生死锁(deadlock)的危险。
性能问题,临界区的大小与执行性能直接相关。首先,获取锁定需要花费时间,其次,线程冲突时必须等待。所以,尽可能缩小临界区的范围,以减少出现线程冲突的机会,可抑制性能的降低。
另外一个问题,synchronized是获取谁的锁定来保护呢?如果实例不同,那么锁定也不同。如果有多个不同的实例,那么多个线程仍然可以分别执行不同实例的synchronized方法。
synchronized方法同时只有一个线程可以执行,当有一个线程正在执行synchronized方法时,其他线程不能进入这个方法。从多线程的角 度看,synchronized方法是原子操作(atomic operation)。在Java语言规格上,long和double的赋值操作并不是原子的。可以在类属性字段前面加上volatile关键字将所有对 该字段的操作变为原子的。
Immutable Pattern
不变模式,该模式的语义与GoF定义的设计模式的不变模式是一样的,即通过定义不变类,来实现线程的安全性。由于类的实例一旦生成,其状态将不会变化,顾其天生就是线程安全的。
使用Immutable Pattern 的Person类
- public final class Person {
- private final String name;
- private final String address;
- public Person(String name, String address) {
- this.name = name;
- this.address = address;
- }
- public String getName() {
- return this.name;
- }
- public String getAddress() {
- return this.address;
- }
- public String toString() {
- return "[ Person: name =" + name + ", address = " + address + " ]";
- }
- }
- public class Main() {
- public static void main(String[] args){
- Person alice = new Person("Alice", "Alaska");
- new PrintPersonThread(alice).start();
- new PrintPersonThread(alice).start();
- new PrintPersonThread(alice).start();
- }
- }
- public class PrintPersonThread extends Thread {
- private Person person;
- public PrintPersonThread(Person persion) {
- this.person = person;
- }
- public void run() {
- while(true) {
- System.out.println(Thread.currentThread().getName() + " prints " + person);
- }
- }
- }
相关推荐
java多线程基础资料,java多线程基础资料
java多线程基础说课PPT教案.pptx
JAVA多线程基础DEMO,都是一些基础演练,希望可以帮到你
Java多线程干货系列(1)Java多线程基础编程开发技术共23页.pdf.zip
java多线程基础知识
Java多线程基础
学习此资源的内容,会让读者对JAVA多线程有一个比较清晰的理解,以至于为今后更深入的学习打下良好的基础
Java多线程基础-01、数组概述.rar
java多线程基础说课学习课程.pptx
java多线程基础说课学习教案.pptx
java多线程基础说课PPT学习教案.pptx
Java多线程基础-02、数组定义方式一、访问、注意事项.rar
涵盖了java中多线程的基础知识,多线程间通讯等
初学者的最好的教程,多线程基础篇讲解,用简洁的语言描述,能够更加容易理解
线程开发05_线程命名06_线程休眠07_线程优先级08_线程礼貌09_关键资源问题关键../等待...源码详情01_串行与并发02_进程与线程"03线程的生命04.线程的开辟05_线程的命名06_线程的休眠07_线程的优先08_线程的礼让09_...
很适合多线程方面的知识的提升。能对java多线程基础有很大的帮助,就是书中的例子太少,源码也少,不适合深入理解探索,不过是本好书。
java多线程小程序实例 java多线程小程序实例
这套课程既可以作为从零基础开始...课程的主要内容涉及有JAVA基础课程、JAVA多线程与并发编程、数据库开发基础和进阶、Spring Framework、Spring进阶、Spring MVC框架、Spring boot、Java常用类库、Java异常处理等等
java多线程基础知识练习题,选择题及代码题。适合初学者
JAVA多线程编程技术探讨,深入JAVA多线程编程技术的基础