2012-07-21 33 views
6

Trong chương trình android của tôi, Activity gọi một lớp xem bề mặt mới, sau đó lần lượt gọi một lớp chủ đề mới. Tôi muốn có thể chuyển một giá trị cho lớp thread từ các phương thức onPause và onResume của hoạt động, vì vậy tôi có thể tạm dừng và tiếp tục luồng. Cách duy nhất tôi biết để truyền dữ liệu này là tạo ra một cá thể mới, nó sẽ tạo ra một luồng khác. Làm thế nào tôi nên đi về điều này mà không cần tạo một thể hiện thread mới?Truyền giá trị từ hoạt động tới chủ đề sau khi chuỗi đã được tạo

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(new GameSurface(this)); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
      //Would like to pass this value 
      int state = 1; 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
      //Would like to pass this value 
      int state = 2; 
} 
+0

Tôi đã cập nhật câu trả lời của mình với 2 lớp và triển khai hoạt động của 'AtomicInteger'. Kính trọng – Killrawr

Trả lời

4

Một nền nhỏ trên đồng thời

Đi qua giá trị trong đồng thời là phần dễ dàng. Nhìn vào loại dữ liệu AtomicInteger (Thông tin thêm here). Nguyên tử cũng có nghĩa là All or nothing. Kiểu dữ liệu này không nhất thiết phải gửi dữ liệu giữa các luồng hoặc bộ xử lý (như bạn làm với mpi) nhưng nó chỉ đơn thuần là chia sẻ dữ liệu trên bộ nhớ dùng chung của nó.

Nhưng những gì là một hành động nguyên tử? ....

Một hoạt động nguyên tử là một hoạt động được thực hiện như một đơn vị công việc mà không có khả năng can thiệp từ các hoạt động khác.

Trong Java, đặc tả ngôn ngữ đảm bảo rằng việc đọc hoặc viết biến là nguyên tử (trừ khi biến có kiểu dài hoặc gấp đôi). Long và đôi chỉ nguyên tử nếu họ khai báo là không ổn định ....

tín dụng (Java Concurrency/Multithreading - Tutorial bởi Lars Vogel)

tôi khuyên bạn đọc này, nó bao gồm tất cả mọi thứ từ atomicity, thread pools, deadlocksthe "volatile" and "synchronized" keyword.


Bắt đầu lớpnày sẽ thực hiện một chủ đề mới (Nó cũng có thể được gọi là Main Thread của chúng tôi).

import java.util.concurrent.atomic.AtomicInteger; 
/** 
* @author Michael Jones 
* @description Main Thread 
*/ 
public class start { 
    private AtomicInteger state; 
    private Thread p; 
    private Thread r; 
    /** 
    * constructor 
    * initialize the declared threads 
    */ 
    public start(){ 
     //initialize the state 
     this.state = new AtomicInteger(0); 
     //initialize the threads r and p 
     this.r = new Thread(new action("resume", state)); 
     this.p = new Thread(new action("pause", state)); 
    } //close constructor 

    /** 
    * Start the threads 
    * @throws InterruptedException 
    */ 
    public void startThreads() throws InterruptedException{ 
     if(!this.r.isAlive()){ 
      r.start(); //start r 
     } 
     if(!this.p.isAlive()){ 
      Thread.sleep(1000); //wait a little (wait for r to update)... 
      p.start(); //start p 
     } 
    } //close startThreads 

    /** 
    * This method starts the main thread 
    * @param args 
    */ 
    public static void main(String[] args) { 
     //call the constructor of this class 
     start s = new start(); 
     //try the code 
     try { 
      s.startThreads(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } //start the threads 
    } //close main 

} //close class start 

Bởi vì số nguyên là nguyên tử, bạn cũng có thể lấy nó ở mọi nơi nhưng main method trong Bắt đầu lớp với System.out.println("[run start] current state is... "+state.intValue());. (Nếu bạn muốn lấy nó ra khỏi main method, bạn sẽ phải thiết lập một setter/getter, như tôi đã làm như vậy trong Vụ Kiện Tập Thể)

Vụ Kiện Tập ThểĐây là chủ đề của chúng tôi trong hành động (Nó cũng có thể được gọi là Slave Thread) của chúng tôi.

import java.lang.Thread.State; 
import java.util.concurrent.atomic.AtomicInteger; 

/** 
* @author Michael Jones 
* @description Slave Thread 
*/ 
public class action implements Runnable { 

    private String event = ""; 
    private AtomicInteger state; 

    /** 
    * The constructor (this represents the current instance of a thread). 
    * 
    * @param event 
    * @param state 
    */ 
    public action(String event, AtomicInteger state) { 
     this.event = event; // update this instance of event 
     this.state = state; // update this instance of state 
    } // constructor 

    /** 
    * This method will be called after YourThreadName.Start(); 
    */ 
    @Override 
    public void run() { 
     if (this.event == "resume") { 
      this.OnResume(); // call resume 
     } else { 
      this.OnPause(); // call pause 
     } 
    } // close Runnable run() method 

    /** 
    * The resume function Use the auto lock from synchronized 
    */ 
    public synchronized void OnResume() { 
     System.out.println("[OnResume] The state was.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
     this.setAtomicState(2); // change the state 
     System.out.println("[OnResume] The state is.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
    } // close function 

    /** 
    * The pause function Use the auto lock from synchronized 
    */ 
    public synchronized void OnPause() { 
     System.out.println("[OnPause] The state was.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
     this.setAtomicState(1); // change the state 
     System.out.println("[OnPause] The state is.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
    } // close function 

    /** 
    * Get the atomic integer from memory 
    * 
    * @return Integer 
    */ 
    private Integer getAtomicState() { 
     return state.intValue(); 
    }// close function 

    /** 
    * Update or Create a new atomic integer 
    * 
    * @param value 
    */ 
    private void setAtomicState(Integer value) { 
     if (this.state == null) { 
      state = new AtomicInteger(value); 
     } else 
      state.set(value); 
    } // close function 

} // close the class 

Console Output

[OnResume] The state was..0 // Thread: 9 
[OnResume] The state is..2 // Thread: 9 
[OnPause] The state was..2 // Thread: 10 
[OnPause] The state is..1 // Thread: 10 

Như bạn có thể thấy, AtomicInteger state đang được chia sẻ trong bộ nhớ giữa các chủ đề của chúng tôi rp.


Giải pháp và Những điều cần tìm kiếm ...

Điều duy nhất bạn phải xem khi thực hiện đồng thời là Race Conditions/Deadlocks/Livelocks. Một số RaceConditions xảy ra vì Threads được tạo theo thứ tự ngẫu nhiên (Và hầu hết các lập trình viên đều nghĩ trong tập hợp thứ tự tuần tự).

Tôi có dòng Thread.sleep(1000); để Main Thread tôi cung cấp cho các chủ đề nô lệ r một ít thời gian để cập nhật các state (trước khi cho phép p để chạy), do thứ tự ngẫu nhiên của bài.

1) Giữ tham chiếu đến chuỗi và chuyển giá trị bằng phương pháp. tín dụng (SJuan76, 2012)

Trong giải pháp tôi đã đăng tôi làm cho tôi Main Thread (aka class start) như giao tiếp chính của tôi để theo dõi các Atomic Integer cho nô lệ của tôi để sử dụng (aka class action). Chủ đề chính của tôi cũng là updatingmemory buffer cho số Atomic Integer trên nô lệ của tôi (Bản cập nhật trên bộ nhớ đệm xảy ra trong nền của ứng dụng và được xử lý bởi lớp AtomicInteger).

+0

Cảm ơn. Vì vậy, tôi có phải sử dụng một constructor AtomicInteger hoặc phương pháp để trong lớp thread để có được trạng thái cập nhật? Xin lỗi nếu điều đó không đúng. Java khá mới đối với tôi. – zkello

+0

Bạn phải sử dụng khai báo AtomicInteger trong mỗi lớp (nói rằng tôi có một lớp 'foo' tạo một luồng với lớp' boo') Tôi sẽ cần 'AtomicInteger x' được khai báo trong cả hai lớp để nó được chia sẻ qua bộ nhớ. – Killrawr

+0

Cũng thêm 'đồng bộ' vào' onPause() 'và' onResume() 'của bạn, ví dụ' void protected onResume() 'được bảo vệ. Điều này cho phép tự động khóa vào luồng hoặc biến 'state'. Và sẽ tránh được 'Điều kiện Race' có thể. Trân trọng – Killrawr

3

1) Giữ tham chiếu đến chuỗi và chuyển giá trị bằng phương pháp.

2) Trong quá trình tạo chuỗi, hãy truyền cho đối tượng được chia sẻ với Hoạt động. Đặt các giá trị để truyền vào đối tượng, để chủ đề kiểm tra nó thường xuyên cho đến khi tìm thấy các giá trị.

+0

sẽ không phải là giải pháp đầu tiên gây ra điều kiện chủng tộc có thể? nếu một trong hai 'onResume' hoặc' onPause' dựa vào nhau? – Killrawr

1

Tôi sử dụng lớp tham chiếu mà tôi đặt tên là Share Class. Nó có biến với loại volatile.

dễ bay hơi được sử dụng để chỉ ra rằng giá trị của một biến sẽ được sửa đổi bởi khác nhau đề.

public class Share { 
    public static volatile type M_shared; 
} 

thay đổi biến này, bạn nên khóa nó và sau khi thay đổi giá trị, phát hành các khóa. Bạn có thể đọc và viết bằng cách sử dụng Share.M_shared.

Các vấn đề liên quan