導航:首頁 > 操作系統 > androidwait的用法

androidwait的用法

發布時間:2023-05-22 09:27:07

1. android創建子線程

創建後台線程的方法有多種,這里說三種,可以回去試試

1、使用Android系統工具類 AsyncTask(Params,Progress,Result)
AsyncTask是一個輕量級線程,三個泛型參數分別是 Params傳入參數,int型Progress為進度條進度,Result為返回值
要使用AsyncTask,必須繼承之並復寫其中的幾個重要的函數。
onPreExecute(), 該方法將在執行實際的後台操作前被UI thread調用。可以在該方法中做一些准備工作,如在界面上顯示一個進度條。
doInBackground(Params...), 將在onPreExecute 方法執行後馬上執行,該方法運行在後台線程中。這里將主要負責執行那些很耗時的後台計算工作。可以調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
onProgressUpdate(Progress...),在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。
onPostExecute(Result), 在doInBackground 執行完成後,onPostExecute 方法將被UI thread調用,後台的計算結果將通過該方法傳遞到UI thread.

註:Task必須在UI線程中創建,並調用並且只能調用一次execute方法,該方法的參數為傳入的泛型Params。
其餘函數最好不要手動調用,容易造成線程崩潰。多次調用Task,容易造成線程池溢出。

2、使用Handler和HandlerThread
誤區: Handler handler = new Handler ();
handler.post(r);
這種做法看似創建了一個線程,但實際上handler只是直接調用Runnable中的run() 方法,而不執行線程的start()函數,所以這兩句代碼執行後,程序仍然在UI線程中執行。所以我們引入HandlerThread,因為HandlerThread中有一個Looper對象,用以循環消息隊列。
為了使用Looper,必須子類化Handler,並復寫它的構造函數。
class MyHandler extends Handler{
public MyHandler() {}
public MyHandler(Looper looper){
super (looper);
}

public void handleMessage(Message msg){
//....這里運行耗時的過程
}
}
}
handleMessage(Message msg)函數用以接收消息,msg則是從UI線程中發出的消息,可以傳遞各種對象,根據這些對象和數值進行操作。
有了Handler子類,則可以在UI線程中進行創建和初始化
HandlerThread handlerThread = new HandlerThread( "backgroundThread" );
handlerThread.start();
MyHandler myHandler = new MyHandler(handlerThread.getLooper());
Message msg = myHandler.obtainMessage();
//....此處對msg進行賦值,可以創建一個Bundle進行承載
msg.sendToTarget();
之後如果需要調用線程,只要對handler傳入msg,就可以執行相應的過程了
最後,很重要的一點,HandlerThread 不隨Activity的生命周期結束而消亡,所以必須復寫Ondestory(),調用HandlerThread .stop()

3、使用線程同步 synchronized、 wait()、 notify()
使用線程同步機制synchronized實現多線程操作,相對來說比較復雜,但也是靈活性最佳、效率最高的一種做法,在產品開發當中也使用得最廣。本人水平相當有限,也只學得一點皮毛。
synchronized相當於一把鎖,當線程運行的時候,會同時有幾個線程訪問一個對象,對其進行操作或者修改。這可能引起很不良的後果(例如改變判定條件,或者在別的線程還沒使用完的時候對象已經被析構等等),所以必須對一些對象進行加鎖,保證它在同一時間只允許被一個線程訪問。
synchronized使用方法有兩種:
<1> 同步方法在方法名前加入synchronized關鍵字,則該方法在同一時間內只允許一個線程訪問它,其代碼邏輯較為簡單,但使用起來不太靈活,並且大大降低效率,耗時太長的同步方法甚至會使得多線程失去原本的意義成為單線程
<2>同步參數 對某一個代碼塊加鎖,並且以synchronized(obj)的方式,表明該代碼塊內的obj對象是線程同步的。這個做法使得代碼靈活性大大加強,縮小同步代碼塊的范圍,並且可以在不同的函數體和類內進行同步,唯一遺憾的是實現起來比較復雜,容易產生一些問題

而wait()和notify(),必須在synchronized鎖的代碼塊內執行,否則系統將會報錯。
有了以上基礎,就可以很容易的創建後台線程了

Private Runnable backgroundRunnable = new Runnable () {
@Override
public void run() {
if(isFinish){
//.....
break;
}
for(;;){
synchronized(this){
//....寫耗時過程
wait();
}
}
}
}

UI線程中,就是一般的創建線程過程了
Thread backgroundThread = new Thread (backgroundRunnable);
backgroundThread.start();
這樣,在後台線程中會不斷的循環,當執行完一次過程以後就會wait()休眠。然後在OnTouchListener或者OnClickListener內相應的位置執行
synchronized(backgroundRunnable){
backgroundRunnable.notify();
}
當用戶觸摸屏幕產生一個event的時候,線程就會被喚醒,執行下一次循環。
最後,還是內存安全問題,必須復寫Activity中的OnDestory()方法,將標志量isFinish設為false,並且backgroundThread .stop()

2. 如何在android下採用相對時間,實現超時等待的功能

一、函數功能說明

pthread_cond_timedwait 等待一個條件變數,或者超時就會返回

POSIX有兩種時鍾類型

1、CLOCK_REALTIME: 系統范圍內的實時時鍾,是個時鍾,可以通過命令等方式修改該系統時間.
2、CLOCK_MONOTONIC:系統起機時到現在的時間,不能被設置和修改.

pthread_cond_timedwait()在沒有設置條件變數屬性的時候,默認用的是CLOCK_REALTIME時間,
因此在極端情況下會出現實際等待的時間與設置的超時時間不同。
所以,對於linux的超時等待功能,最好是使用CLOCK_MONOTONIC進行實現,並且通過pthread_condattr_setclock實現。

而對於android系統而言,是不支持pthread_condattr_setclock,通過驗證可以採用函數pthread_cond_timedwait_monotonic實現。

下面直接給出代碼的實現功能。

二、超時等待功能

[cpp] view plain
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/times.h>
#include <unistd.h>
#include <time.h>

static pthread_mutex_t s_mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;

void PthreadAttr_Init(void);
unsigned long long getSysTime(void);
void waitTimeout(void);

void PthreadAttr_Init(void)
{
#if defined(ANDROID)

#else
pthread_condattr_t cattr;
int iRet = -1;
iRet = pthread_condattr_init(cattr);
if (iRet != 0)
{
return;
}
pthread_mutex_init(s_mut, NULL);
pthread_condattr_setclock(cattr, CLOCK_MONOTONIC);
pthread_cond_init(s_cond, cattr);
pthread_condattr_destroy(cattr);
#endif
return;
}

void waitTimeout(void)
{
unsigned long long ullbefore = getSysTime();
unsigned long long ullafter = 0;

#if defined(ANDROID)

#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) // 支持ANDROID下NDK的編譯,採用相對時間
struct timespec outtime;
memset(outtime, 0x00, sizeof(struct timespec ));
clock_gettime(CLOCK_MONOTONIC, outtime);
outtime.tv_sec += 2;
pthread_mutex_lock(s_mut);
pthread_cond_timedwait_monotonic(s_cond,s_mut, outtime);
pthread_mutex_unlock(s_mut);
ullafter = getSysTime();
printf("####01 interval[%lld] ms\n", ullafter - ullbefore);
#else //支持ANDROID下NDK的編譯,採用絕對時間
struct timeval now;
struct itmespec outtime;
gettimeofday(now, NULL);
outtime.tv_sec = now..tv_sec + 3;
outtime.tv_nsec = now.tv_usec * 1000;
pthread_mutex_lock(s_mut);
pthread_cond_timedwait(s_cond, s_mut, outtime);
pthread_mutex_unlock(s_mut);
ullafter = getSysTime();
printf("####02 interval[%lld] ms\n", ullafter - ullbefore);
#endif

#else // 支持LINUX下的編譯,採用絕對時間
struct timespec outtime;
memset(outtime, 0x00, sizeof(struct timespec ));
clock_gettime(CLOCK_MONOTONIC, outtime);
outtime.tv_sec += 4;
pthread_mutex_lock(s_mut);
pthread_cond_timedwait(s_cond, s_mut, outtime);
pthread_mutex_unlock(s_mut);
ullafter = getSysTime();
printf("####03 interval[%lld] ms\n", ullafter - ullbefore);
#endif
return;
}

unsigned long long getSysTime(void)
{
unsigned long long milliseconds = 0;

struct tms t_tmsTime;
clock_t t_CurTime;
static int s_clks_per_sec = 0;

if (s_clks_per_sec == 0)
{
s_clks_per_sec = sysconf(_SC_CLK_TCK);
}

if (s_clks_per_sec == 0)
{
return 0;
}

t_CurTime = times(t_tmsTime);

if (1000 % s_clks_per_sec == 0)
{
milliseconds = (1000 /s_clks_per_sec)*(unsigned long long )t_CurTime;//換算成毫秒
}
else
{
milliseconds = 1000 * (unsigned long long )t_CurTime/s_clks_per_sec;//換算成毫秒
}

return milliseconds;
}

int main(void)
{
PthreadAttr_Init();
waitTimeout();
return 0;
}

編譯命令:
gcc test_ptthrad_conf_timewait_monotonic.c -o test_ptthrad_conf_timewait_monotonic -lpthread -lrt

linux下的測試結果:
####03 interval[4010] ms

3. Android怎麼正確使用wait和notify方法

synchronized(obj) {
while(!condition) {
obj.wait();
}
obj.doSomething();
}
當線程A獲得了obj鎖後,發現唯豎念條件condition不滿足,無法繼續下一處理,於是線程A就wait() , 放棄對象鎖.
之後在另一線程B中,如果B更改了某些條件,使得線程A的condition條件滿足了,就可以喚醒線程A:
synchronized(obj) {
condition = true;
obj.notify();
}
需要注意的概念是:
# 調用obj的wait(), notify()方法前,必須獲得obj鎖,也就是必須寫在synchronized(obj) {…} 代碼段內。
# 調用obj.wait()後,線程A就釋放了obj的鎖,否則線程B無法獲得obj鎖,也就無法在synchronized(obj) {…} 代碼段內喚醒A。
# 當obj.wait()方法返回後,線程A需要再次獲得obj鎖,才能繼續執行。
# 如果A1,A2,A3都在obj.wait(),纖蠢則B調用obj.notify()只能喚醒A1,A2,A3中的一個(具體哪一個由JVM決定)。
# obj.notifyAll()則能全部喚醒A1,A2,A3,但是要繼續指困執行obj.wait()的下一條語句,必須獲得obj鎖,因此,A1,A2,A3隻有一個有機會獲得鎖繼續執行,例如A1,其餘的需要等待A1釋放obj鎖之後才能繼續執行。
# 當B調用obj.notify/notifyAll的時候,B正持有obj鎖,因此,A1,A2,A3雖被喚醒,但是仍無法獲得obj鎖。直到B退出synchronized塊,釋放obj鎖後,A1,A2,A3中的一個才有機會獲得鎖繼續執行

4. android java 線程 wait()函數

簡單說wait必須顯示用代碼喚醒。
wait是Object的方法,也就是說可以對任意一個對象調用wait方法,調用wait方法將會將調用者的線程掛起,直到其他線程調用同一個對象的notify方法才會重新激活調用者,例如:
//Thread 1
try{
obj.wait();//suspend thread until obj.notify() is called
}
catch(InterrputedException e) {
}

5. Android怎麼正確使用wait和notify方法

經常有人有以下的說法:
notify只會通知一個在等待的對象,而notifyAll會通知所有在等待的對象,並且所有對象都會繼續運行

並且,好像都有例子可以證明。上面的說法,可以說對,也可以說不對。究其原因,在於其中有一點很關鍵,官方的說法如下所示:
wait,notify,notifyAll:
此方法只應由作為此對象監視器的所有者的線程來調用。通過以下三種方法之一,線程可以成為此對象監視器讓慎的所有者:
通過執行此對象的同步實例方法。
通過執行在此對象上進行同步的 synchronized 語句的正文。
對於 Class 類型的對象,可以通過執行該類的同步靜態方法。
一次只能有一個線程擁有對象的監視器。

以上說法,摘自javadoc。意思即,在調用中,必須持有對象監視器(即鎖),我們可以理解為需要在synchronized方法內運行。那麼由此話的隱含意思,即如果要繼續由同態滑答步塊包含的代碼塊,需要重新獲取鎖才可以。這句話,在javadoc中這樣描述:

wait
此方法導致當前線程(稱之為 T)將其自身放置在對象的等待集中,然後放棄此對象上的所有同步要求。出於線程調度
目的,在發生以下四種情況之一前,線程 T 被禁用,且處於休眠狀態:
其他某個線程調用此對象的 notify 方法,並且線程 T 碰巧被任選為被喚醒的線程。
其他某個線程調用此對象的 notifyAll 方法。
其他某個線程中斷線程 T。
大約已經到達指定的實際時間。但是,如果 timeout 為零,則不考慮實際時間,在獲得通知前該線程將一直等待。
然後,從對象的等待集中刪除線程 T,並重新進行線程調度。然後,該線程以常規方式與其他線程競爭,以獲得在該對
象上同步的權利;一旦獲得對該對象的控制權,該對象上的所有其同步聲明都將被恢復到以前的狀態,這就是調用 wait
帆慧方法時的情況。然後,線程 T 從 wait 方法的調用中返回。所以,從 wait 方法返回時,該對象和線程 T 的同步狀態與調
用 wait 方法時的情況完全相同。

即必須重新進行獲取鎖,這樣對於notifyAll來說,雖然所有的線程都被通知了。但是這些線程都會進行競爭,且只會有一個線程成功獲取到鎖,在這個線程沒有執行完畢之前,其他的線程就必須等待了(只是這里不需要再notifyAll通知了,因為已經notifyAll了,只差獲取鎖了)有如下一個代碼,可以重現這個現象。

6. Android如何阻塞一個線程讓其等待一個時間發生之後再繼續執行

你所謂的線程阻塞是指的ui線程嗎?這應該是從你在開發的經驗以及測試當中去體驗的,如果你說是用代碼去判斷線程阻塞的話,估計比較復雜,也沒那個必要,android的機制在出現ui線程阻塞的話會出現anr給予用戶提示,出現這樣的情況是開發者在開發過程中就得去避免的!

7. Android怎麼正確使用wait和notify方法

不知道你正在試圖做。 您可以使用下面,以供參考。

如果你實現Thread or HandlerThread ,確保您的UI線程不會阻塞而等待工作線程完成不致電Thread.wait()或Thread.sleep()

檢查developer.android.com/training/articles/perf-anr.html

你不應該阻止你的主UI線程。 而不是一個定時器,你可以使用一個'處理器'

您可以啟動和停止定時器按鈕點擊。 您可以重新安排您的定時器計數值。 你需要照顧的方向變化的桐此活動被銷毀並重新創建。 count的值,我們將重新初始化。
MainActivity.java

public class MainActivity extends Activity implements OnClickListener{

Timer t;
int count = 0;
boolean isDone = true;
Button b;
TextView tv;

Thread thread;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

b = (Button) findViewById(R.id.button1);
tv = (TextView) findViewById(R.id.textView1);

t = new Timer();
t.scheleAtFixedRate(new TimerTask() {

@Override
public void run() {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
public void run() {
tv.setText(String.valueOf(count));
if(isDone)
count++;

}
});
}
}, 1000, 1000);

b.setOnClickListener(this);

}

@Override
public void onClick(View v) {
// TODO Auto-generated method stu

final Dialog d = new Dialog(MainActivity.this);
d.setTitle("Pause Menu");
d.setContentView(R.layout.pausemenu);
Button b1 = (Button) d.findViewById(R.id.button1);
Button b2 = (Button) d.findViewById(R.id.button2);

b1.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
t.cancel();
d.dismiss();

}
});

b2.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
//局殲迅 TODO Auto-generated method stub
if(isDone)
{
t.cancel();
isDone=false;
改信}
t = new Timer();
t.scheleAtFixedRate(new TimerTask() {

@Override
public void run() {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
public void run() {
tv.setText(String.valueOf(count));
count++;
}
});
}
}, 1000, 1000);
d.dismiss();
}
});
d.show();

}
}
main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="20sp"
android:text="TextView" />

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignRight="@+id/textView1"
android:layout_marginBottom="21dp"
android:text="Button" />

</RelativeLayout>

pausemenu.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="118dp"
android:layout_marginLeft="51dp"
android:text="Stop" />

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button1"
android:layout_alignBottom="@+id/button1"
android:layout_marginLeft="32dp"
android:layout_toRightOf="@+id/button1"
android:text="Start" />

</RelativeLayout>
編輯:
使用處理程序

Handler m_handler;
Runnable m_handlerTask ;
m_handlerTask = new Runnable()
{
@Override
public void run() {
if(isDone)
{
tv.setText(""+count);
count++;
m_handler.postDelayed(m_handlerTask, 1000);
}
// m_handler.removeCallbacks(m_handlerTask);
}
};
m_handlerTask.run();
你應該停止定時器和處理程序時,不需要取消。

如果你t.cancel()使用定時器和使用m_handler.removeCallbacks(m_handlerTask)停止處理程序呼叫

閱讀全文

與androidwait的用法相關的資料

熱點內容
照片怎麼轉換成pdf 瀏覽:129
女生學編程好嗎 瀏覽:238
目前絕地求生怎麼看伺服器地址大全 瀏覽:825
論人類不平等的起源pdf 瀏覽:436
壓縮機螺桿加工 瀏覽:368
怎麼把網站伺服器設置在境外 瀏覽:162
單片機編程取反 瀏覽:897
51單片機課程設計課題 瀏覽:900
手機淘寶登錄怎麼加密碼 瀏覽:486
linux快捷方式圖標 瀏覽:38
陽光車險的app叫什麼名字 瀏覽:462
購買單片機的器件時需要給商家啥 瀏覽:535
並行編譯技術的發展 瀏覽:550
阿里雲伺服器安裝管理 瀏覽:551
java手機開發教程 瀏覽:675
我的世界怎麼刪除伺服器數據 瀏覽:672
linux內存子系統 瀏覽:973
加密思維幣 瀏覽:691
魅族訪客文件夾 瀏覽:53
添加的文件夾怎麼找 瀏覽:618