导航:首页 > 操作系统 > 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的用法相关的资料

热点内容
amdlinux显卡安装 浏览:564
泰海科技云服务器如何卸载 浏览:122
有密码打开excel加密 浏览:818
java生成重复字符 浏览:280
串口服务器有什么用 浏览:328
linux安装red5 浏览:295
单片机中断时入口地址作用 浏览:148
程序员的工作是重复性的吗 浏览:67
照片怎么转换成pdf 浏览:133
女生学编程好吗 浏览:240
目前绝地求生怎么看服务器地址大全 浏览:825
论人类不平等的起源pdf 浏览:436
压缩机螺杆加工 浏览:369
怎么把网站服务器设置在境外 浏览:164
单片机编程取反 浏览:897
51单片机课程设计课题 浏览:900
手机淘宝登录怎么加密码 浏览:486
linux快捷方式图标 浏览:38
阳光车险的app叫什么名字 浏览:462
购买单片机的器件时需要给商家啥 浏览:535