① android里有哪些方法启动线程
其实Android启动线程和java一样有两种方式,一种是直接Thread类的start方法,也就是一般写一个自己的类来继承Thread类。另外一种方式其实和这个差不多啊! 那就是Runnable接口,然后把Runnable的子类对象传递给Thread类再创建Thread对象.总之都是需要创建Thread对象,然后调用Thread类的start方法启动线程。区别就是,一个是直接创建Thread对象,另外一个是需要implement了Runnable接口对象作为创建Thread对象的参数。Runnable其实我们称为线程任务。
第一种方式一般是这样用:
Class MyThread extends Thread{
public void run(){
//你要实现的代码
}
}
在主线程中启动这个线程:
public class Test{
public static void main(String[] args){
new MyThread().start();//启动了我们的线程了
}
}
2,第二种方式一般是这样用:
public class MyRunnable implements Runnable{
public void run(){
//你需要实现的代码
}
}
在主线程中启动这个线程:
public class Test{
public static void main(String[] args){
Thread t=new Thread(new MyRunnable());//这里比第一种创建线程对象多了个任务对象
t.start();
}
}
这里我想说的是可能你问这个问题是接触到了Android中的Handler概念:
其实Handler并不是开辟新线程的概念,Android主要的考虑到更新界面的问题,一般情况下,更新界面(Activity)都是在主线程中更新的,这样就遇到了一个问题,比方说:在下载文件时候我们需要进度条显示下载进度,界面需要更新(数据是不断变的,也就是下载的大小是不断变的,要是直接在主线程中更新,就会造成程序的堵塞,程序很容易崩溃,通常这样联网耗时的工作需要开辟另外一个线程的,这样就不会影响主程序了),好了,到这里联网操作一般都需要开辟新线程了吧。。
接下来就来说Handler了,刚刚我说了Handler不是开辟新线程,在我看来,Handler更像是主线程的秘书,是一个触发器,负责管理从子线程中得到更新的数据,然后在主线程中更新界面。简单说下进度条的那个:
下载了多少的数据都是在子线程中得到的,在子线程中通过Handler的sendMessage()方法发送得到的下载的数据,当你调用了sendMessage方法后,Handler就会回调(也就是自动调用)Handler中的 HandlerMessage方法。
我很认真写了,希望分给我! 要是还有不懂的,可以追问,总之Handler不是开辟线程,开辟线程的方式就和JAVA一样的! 千万不要被Android中的Handler混淆。
② Android中的线程池
线程池的好处
1、重用线程池中的线程,避免线程的创建与销毁带来的性能开销
2、能有效控制线程池的最大并发数,避免大量线程因抢占资源而导致的阻塞
3、能对线程进行简单的管理,提供定时或者指定间隔时间、循环执行等操作
线程池的概率来自于java的Executor接口,实现类是ThreadPoolExecutor, 它提供一系列的参数来配置线程池,以此构建不同的线程池。Android的线程池分4类,都是通过Executors所提供的工厂方法来得到。
ThreadPoolExecutor有四个构造函数,下面这个是最常用的
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnnable> workQueue, ThreadFactory threadFactory)
corePoolSize
线程池中的核心线程数,默认情况下核心线程会在线程池中一直存活,即使他们处于闲置状态。如果设置ThreadPoolExecutor 中的allowCoreThreadTimeOut = true, 核心线程在等待新任务到来时有超时机制,时间超过keepAliveTime所指定的时间后,核心线程会终止。
maximumPoolSize
最大线程数
keepAliveTime
非核心线程闲置的超时时间,超过这个时间,非核心线程会被回收。核心线程则要看allowCoreThreadTimeOut属性的值。
unit
时间单位
workQueue
线程池中的工作队列
threadFactory
线程工厂,为线程池提供创建新线程的功能。
举个例子,我们常用的okhttp内部也是使用了线程池,它的ThreadPoolExecutor主要是定义在Dispatcher类里面。 使用的是CachedThreadPool。
executorService = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS, SynchronousQueue(), ThreadFactory("okhttp Dispatcher", false))
1、FixedThreadPool
通过Executors的newFixedThreadPool()创建,这是一个线程数量固定的线程池,里面所有的线程都是核心线程。
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
}
2、CachedThreadPool
通过Executors的newCacheThreadPool()创建,这是一个线程数量不定的线程池,里面所有的线程都是非核心线程。最大线程数是无限大,当线程池中的线程都处于活动状态时,新的task会创建新的线程来处理,否则就使用空闲的线程处理,所有的线程都是60s的超时时间,超时后会自动回收。
public static ExecutorService newFixedThreadPool(){
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>())
}
3、ScheledThreadPool
通过Executors的newScheledThreadPool()创建, 核心线程固定,非核心线程无限大,当非核心线程空闲时,会立即被回收。适合做定时任务或者固定周期的重复任务。
public static ExecutorService newScheledThreadPool(int corePoolSize){
return new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.SECONDS, new DelayedWorkQueue())
}
4、SingleThreadExcecutor
通过Executors的newSingleThreadPool()创建,内部只有一个核心线程。
public static ExecutorService newFixedThreadPool(){
return new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
}
课外知识:LinkedBlockingQueue
LinkedBlockingQueue是由链表组成的阻塞队列,内部head 指向队列第一个元素,last指向最后一个元素。入队和出队都会加锁阻塞,都是使用了不同的锁。
DelayedWorkQueue
延时队列,队内元素必须是Delayed的实现类。对内元素会按照Delayed时间进行排序,对内元素只有在delayed时间过期了才能出队。
入队的时候不阻塞队列,出队的时候,如果队列为空或者队列里所有元素都等待时间都没有到期,则该线程进入阻塞状态。
③ 如何为android添加新的线程
new Thread(new Runnable(){
public void run(){
//TODO
//在这里写要处理的操作,子线程中不能处理举裂手UI的操作(如:源谈textView.setText("cc");),否则报错
}
}
).start();
这样就开了新的线程了。
线程可以结合Handler来使用,需要获取线程内部的消息,可正嫌以使用Handler将消息发送到UI主线程中。
④ android开发中,如何在做一些耗时的操作时,另起一个新线程
handler其实就是消息处理机制。首先在主线程也就是UI创建一个Handler对象,复写其中的handMessage( Message msg)方法。该方法里的msg就是子线程发来的消息,表示子线程处理完了,以这个msg来通知主线程。让主线程来作UI的绘制工作。
那么子线程工作完了就要发消息了,比如:
run(){
data = getDataFromInternet();//耗时工作
Message msg = handler.obtainMessage(0, data);//通过handler得到消息,该消息的标识为0,消息内容是data
handler.sendMessage(msg);//发送
}
然后handler在主线程就负责接收:
public Handler handler = new Handler(){//处理UI绘制
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
data = (List<Map<String, Object>>) msg.obj;
if(data == null){
Toast.makeText(AllMovieActivity.this, "网络连接失败,获取不到影片信息", 1).show();
}else {
adapter = new HotMoviedapter(AllMovieActivity.this, data, R.layout.allmovielist_item,
new String[] { "picurl", "chname", "director", "leadrole",
"fshowtime", "country" }, new int[] { R.id.picurl,
R.id.chname, R.id.director, R.id.leadrole,
R.id.fshowtime, R.id.country },mListView);
TextView v = new TextView(AllMovieActivity.this);
v.setHeight(80);
v.setSelectAllOnFocus(false);
mListView.addFooterView(v);
mListView.setAdapter(adapter);
}
break;
default:
break;
}
}
};
⑤ android开发中,如何在做一些耗时的操作时,另起一个新线程20170819 13:21
1、第一种方式:使用Thread不带参数的构造方法,并重写run()方法<pre t="code" l="as3">new Thread(){
public void run(){
//在run方法中调用需要执行的代码,完成后发送消息与主线程交互
Message msg=new Message();
msg.what=110;
handler.sengMessage();
}
}.start();2、第二种方式:使用Thread带参数的构造方法,并重写Runable()中的run方法<pre t="code" l="java">new Thread(new Runable(){
public void run(){
//在run方法中调用需要执行的代码,完成后发送消息与主线程交互
Message msg=new Message();
msg.what=110;
handler.sengMessage();
}).start();3、在UI线程中接收Thread子线程发送的消息,刷新UI界面
⑥ 求教android在新线程中调用webview方法的最佳实践
{
staticandroid.os.Handlerh=null;
staticWebVieww=null;
publicstaticvoidgetWebView(WebVieww0){//有点想不起来webview的类名是啥了,强答
w=w0;
h=newandroid.os.Handler();//请用UI线程来运行这段代码
}
publicstaticvoiddoWithWebView(){
newThread(){//开新线程
@Overridepublicvoidrun(){
try{//里面写新线程执行内容
/*
XXX耗时内容烂神……
*/
大凳h.post(newRunnable(){//用handler转交UI处理操作
@Overridepublicvoidrun(){
//在这写操作webview的代码
//请不要在这里放耗时代码,否则会卡住UI线程
饥仿亏}
});
}catch(Exceptione){
}
}
}.start();
}
}
//PS:因为我已经不记得如果对象声明在方法内部如何用final,所以索性写成这样。没环境写JAVA,所以可能有几个小错误
⑦ android 新添加线程 怎么让他不再主线程里执行
子线程就是一个新的线程,不会再主线程执行,你说的是在主线程开启子线程吧、
⑧ Android中是不是新开一个activity就是新建了一个线程
不是的,Android中所有的Activity都是在一个线丛携程中,也就是我们所说的主帆隐线程(UI线程)。另外Activity 和 线程本身是两个跨度很大的概念。渗轿伏
⑨ android开发中线程有几种状态,分别是哪些
【答案】:1)、新建状态(New):新创建了一个线程对象。
2)、就绪状态(Runnable):线程对象创建后,前蚂消其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3)、运行状态(Running):就绪状态的线程获取了CPU,执行run()方法。
4)、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞慧知:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁物卜池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5)、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
当调用start方法的时候,该线程就进入就绪状态。等待CPU进行调度执行,此时还没有真正执行线程。
当调用run方法的时候,是已经被CPU进行调度,执行线程的主要任务。
⑩ Android中的线程和线程池
一、除了Thread外,扮演线程角色的还有:AsyncTask和IntentService,同时HandlerThread也扮演特殊的线程。
IntentService:内部采用HandlerThread来执行,像一个后台线程,同时是一个服务,不容易被系统杀死。
二、HandlerThread的run方法是一个无限循环
三、IntentService中任务是排队执行的
四、AsyncTask
1、Android1.6之前串悄段桐行执行任务,1.6时候采用线程池里的并行,Android3.0开始又开始串行(为了避免并发错误),单任可以并行。
2、AsyncTask必须在UI线程调用(不过这个不是绝对的,和版本有关燃腔系,API 16之前,API 16到 22, API 22以后) 参考一
原因:内部有静态Handler,采用UI线程的Looper来处理消息,这就是为什么AsyncTask必须在UI线程调用,因为子线程默认没有Looper无法创建下面的Handler,程序会直接Crash
3、AsyncTask中有两个线程池和一个Handler,一个线程池用启坦于任务排队,一个线程池用于真正的执行任务,InternalHandler用于将
执行环境从线程池切换到主线程
AsyncTask串行与并行
五、线程池
线程池中多余的线程是如何回收的