一:线程创建的几种方式
a:new Thread(newRunable(){}).start(),这种方式创建方式如果过多的话,会可能导致死机和oom
b:AsyncTask来创建线程,它里面有三种执行方法(AsyncTask已经被废弃)
1)execute(),这里面试串行执行的,所以创建的多时.某个线程出问题就会阻塞
2)executeOnExecutor()
3)AsyncTask.THREAD_POOL_EXECUTOR.execute(),通过内置的线程池进行开启线程
c:HandlerThread:适用于主线程和工作线程通讯,但是它和普通的线程不一样,它执行完任务后不会被销毁,会一直运行
d:IntentService:适用于需要跨页面读取任务执行进度,比如后台上传图片,批量执行数据库
e:ThreadpoolExactor:线程池的方式创建线程,适用于快速处理大量耗时较短的任务场景
二:线程的优先级,jdk通过Thread.setPriority(int newPriority)来设置优先级,但是这种设置优先级只能设置1-10,数字越大优先级越高,
google在android中提供了另外一种设置线程优先级的方式android.os.process.setThreadPriority(int newPriority),取值范围是-20~19,数值越小优先级越高和java相反
1.wait和notify:进入等待池,释放资源锁对象,可以使用notify,notifyAll.或者等待超时进行唤醒,顺序wait->notify
Object object = new Object();
class Runnable implements java.lang.Runnable{
@Override
public void run() {
//因为wait方法是object的,所以我们要给它绑定一个对象
synchronized (object){//锁对象
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.d("ConcurrentTest","线程");
}
}
class Runnable1 implements java.lang.Runnable{
@Override
public void run() {
//因为wait方法是object的,所以我们要给它绑定一个对象
synchronized (object){//锁对象
object.notify();//唤醒wait的线程
}
Log.d("ConcurrentTest","线程1");
}
}
new Thread(new Runnable()).start();
new Thread(new Runnable1()).start();
2.join等待目标线程执行完成后再执行此线程
3.yidld:暂停当前正在执行的线程
4.sleep:使当前线程处于休眠状态,当sleep执行在synchronized中时,虽然当前线程会休眠,但是当前线程不会释放当前的锁资源
三:如何实现主线程向子线程发送消息
//创建一个子线程,想要对消息进行处理,所以我们要给当前的子线程创建looper
class LooperThread extends Thread{
private Looper myLooper;
public LooperThread(String name) {
super(name);
}
public Looper getMyLooper() {
if (null==myLooper){
synchronized (this){
try {
wait();//等待创建好looper实例后被唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return myLooper;
}
@Override
public void run() {
super.run();
Looper.prepare();
//将Looper保存
synchronized (this){
myLooper = Looper.myLooper();
notify();
}
Looper.loop();
}
}
//在主线程中进行消息发送
LooperThread looperThread = new LooperThread("looper-thread");
looperThread.start();
Handler handler = new Handler(looperThread.getMyLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
Log.d("ConcurrentTest",Thread.currentThread().getName());
}
};
handler.sendEmptyMessage(0);
四:线程的并发与安全,场景:12306卖票场景
线程安全的几种分类
a:synchronize关键字:加锁是为了保证写的时候操作数据时的安全性,比如我们在同一时间开启多个线程来写入数据,这时候可以加锁来保证数据的安全正确
b:ReentrantLock锁:悲观锁,可重入锁,公平锁,非公平锁
c:AtomicInter...原子类:它不需要加锁,它是直接获取后台数据进行操作,判断内存中的同步资源是否被更新,来进行操作,所以它适合读的操作场景(原子类)
volatile:这个如果子作用于正常的单类似于x=1这种赋值操作能保证线程安全,但是执行x++这种其实多步操作时不安全的,我们可以使用原子类:AtomicInter来保证线程安全
synchronize:
1.可以修饰方法上,表示当有人访问当前锁对象时,如果有人已经访问了,当前的人要等待,等待后再去和其他的人竞争锁对象,
public synchronized void print(){//多个对象访问时,要排队才能进行访问
}
2.如果synchronize加载代码块上,未获取锁的对象可以访问代码块外的代码
3.可以将锁加载class上,class文件只有一个,对象有多个,所以无论是不是同一个java对象去访问同步访问,都需要排队
ReentrantLock用法,因为不会像synchronize一样会自动释放锁,所有我们加了锁后要自己释放锁
ReentrantLock lock = new ReentrantLock();
try {
lock.lock();
}finally {
lock.unlock();
}