开启线程的三种方式?
1)继承Thread类创建线程
2)实现Runnable接口创建线程
3)使用Callable和Future创建线程
Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大。
call()方法可以有返回值
call()方法可以声明抛出异常
线程和进程的区别?
进程是指程序执行时的一个实例。
线程是进程的一个实体。
进程——资源分配的最小单位,线程——程序执行的最小单位。
一个程序至少有一个进程,一个进程至少有一个线程
线程执行开销小,但不利于资源的管理和保护;
而进程正相反。
为什么要有线程,而不是仅仅用进程?
程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。
进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。
run()和start()方法区别
start():该方法是在当前线程中启动一个新的线程,而新启动的线程会调用run()方法,同时该方法不能重复调用;
run() :该方法和普通的方法一样,可以重复执行,不会创建新的线程。
public class StartAndRunDemo {
public static void main(String[] args) {
Thread t1 = new MyThread("thread_01");
System.out.println("run() ....");
t1.run();
System.out.println("start() ....");
t1.start();
//run()方法可以重复执行
//t1.run();
//start()方法不能重复执行,重复执行会抛出java.lang.IllegalThreadStateException
//t1.start();
}
static class MyThread extends Thread{
public MyThread(String name){
super(name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is running!");
}
}
}
输出的结果是:
run() ....
main is running!
start() ....
thread_01 is running!
原文:https://blog.youkuaiyun.com/tianmlin1/article/details/79054304
①在main方法中执行的run()方法不会创建新的线程,而在main方法中执行的start()方法会启动一个新的线程,新的线程会调用run方法
②run方法可以多次执行,但是start方法不允许多次执行,多次执行start()方法会抛出一个一个运行时异常java.lang.IllegalThreadStateException
如何控制某个方法允许并发访问线程的个数?
使用Semaphore控制某个方法允许并发访问的线程的个数
semaphore.acquire() 请求一个信号量,这时候的信号量个数-1(一旦没有可使用的信号量,也即信号量个数变为负数时,再次请求的时候就会阻塞,直到其他线程释放了信号量)
semaphore.release() 释放一个信号量,此时信号量个数+1
public class SemaphoreTest {
private Semaphore mSemaphore = new Semaphore(5);
public void run(){
for(int i=0; i< 100; i++){
new Thread(new Runnable() {
@Override
public void run() {
test();
}
}).start();
}
}
private void test(){
try {
mSemaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 进来了");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 出去了");
mSemaphore.release();
}
}
原文:https://blog.youkuaiyun.com/anhenzhufeng/article/details/70225415
示例中实例化了具有5个信号量的semaphore,保证只有5个线程在执行test方法
04-18 17:05:46.350 14192-14228/com.tongxt.myapplication I/System.out: Thread-1228 进来了
04-18 17:05:46.351 14192-14231/com.tongxt.myapplication I/System.out: Thread-1231 进来了
04-18 17:05:46.354 14192-14233/com.tongxt.myapplication I/System.out: Thread-1233 进来了
04-18 17:05:46.354 14192-14232/com.tongxt.myapplication I/System.out: Thread-1232 进来了
04-18 17:05:46.355 14192-14234/com.tongxt.myapplication I/System.out: Thread-1234 进来了
04-18 17:05:47.351 14192-14228/com.tongxt.myapplication I/System.out: Thread-1228 出去了
04-18 17:05:47.351 14192-14236/com.tongxt.myapplication I/System.out: Thread-1236 进来了
04-18 17:05:47.352 14192-14231/com.tongxt.myapplication I/System.out: Thread-1231 出去了
04-18 17:05:47.352 14192-14235/com.tongxt.myapplication I/System.out: Thread-1235 进来了
04-18 17:05:47.354 14192-14233/com.tongxt.myapplication I/System.out: Thread-1233 出去了
04-18 17:05:47.354 14192-14237/com.tongxt.myapplication I/System.out: Thread-1237 进来了
04-18 17:05:47.354 14192-14232/com.tongxt.myapplication I/System.out: Thread-1232 出去了
04-18 17:05:47.354 14192-14229/com.tongxt.myapplication I/System.out: Thread-1229 进来了
04-18 17:05:47.356 14192-14234/com.tongxt.myapplication I/System.out: Thread-1234 出去了
04-18 17:05:47.356 14192-14230/com.tongxt.myapplication I/System.out: Thread-1230 进来了
04-18 17:05:48.351 14192-14236/com.tongxt.myapplication I/System.out: Thread-1236 出去了
在Java中wait和seelp方法的不同;
一.java中的sleep()和wait()的区别;
对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
public class TestD {
public static void main(String[] args) {
new Thread(new Thread1()).start();
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(new Thread2()).start();
}
private static class Thread1 implements Runnable {
@Override
public void run() {
synchronized (TestD.class) {
System.out.println("enter thread1...");
System.out.println("thread1 is waiting...");
try {
// 调用wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池
TestD.class.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread1 is going on ....");
System.out.println("thread1 is over!!!");
}
}
}
private static class Thread2 implements Runnable {
@Override
public void run() {
synchronized (TestD.class) {
System.out.println("enter thread2....");
System.out.println("thread2 is sleep....");
// 只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
TestD.class.notify();
// ==================
// 区别
// 如果我们把代码:TestD.class.notify();给注释掉,即TestD.class调用了wait()方法,但是没有调用notify()
// 方法,则线程永远处于挂起状态。
try {
// sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,
// 但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
// 在调用sleep()方法的过程中,线程不会释放对象锁。
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread2 is going on....");
System.out.println("thread2 is over!!!");
}
}
}
}
这个没有注解掉:TestD.class.notify()的图片
这是注解掉TestD.class.notify()的图片;
这时候thread1 一直处在挂起的状态
谈谈wait/notify关键字的理解
什么导致线程阻塞?
A、线程执行了Thread.sleep(int millsecond);方法,当前线程放弃CPU,睡眠一段时间,然后再恢复执行
B、线程执行一段同步代码,但是尚且无法获得相关的同步锁,只能进入阻塞状态,等到获取了同步锁,才能回复执行。
C、线程执行了一个对象的wait()方法,直接进入阻塞状态,等待其他线程执行notify()或者notifyAll()方法。
D、线程执行某些IO操作,因为等待相关的资源而进入了阻塞状态。比如说监听system.in,但是尚且没有收到键盘的输入,则进入阻塞状态。
线程如何关闭?
https://blog.youkuaiyun.com/moonpure/article/details/80414104
讲一下java中的同步的方法
https://www.cnblogs.com/jiansen/p/7351872.html
数据一致性如何保证?
如何保证线程安全?
如何实现线程同步?
两个进程同时要求写或者读,能不能实现?如何防止进程的同步?
线程间操作List
分段操作
https://www.cnblogs.com/huangdabing/p/9251598.html
Java中对象的生命周期
https://www.cnblogs.com/mengfanrong/p/4007456.html
Synchronized用法
synchronize的原理
谈谈对Synchronized关键字,类锁,方法锁,重入锁的理解
https://blog.youkuaiyun.com/u012545728/article/details/80843595
static synchronized 方法的多线程访问和作用
同一个类里面两个synchronized方法,两个线程同时访问的问题
volatile的原理
谈谈volatile关键字的用法
谈谈volatile关键字的作用
谈谈NIO的理解
synchronized 和volatile 关键字的区别
synchronized与Lock的区别
ReentrantLock 、synchronized和volatile比较
ReentrantLock的内部实现
lock原理
死锁的四个必要条件?
怎么避免死锁?
对象锁和类锁是否会互相影响?
什么是线程池,如何使用?
Java的并发、多线程、线程模型
谈谈对多线程的理解
多线程有什么要注意的问题?
谈谈你对并发编程的理解并举例说明
谈谈你对多线程同步机制的理解?
如何保证多线程读写文件的安全?
多线程断点续传原理
https://blog.youkuaiyun.com/qq_32101859/article/details/53177428
https://blog.youkuaiyun.com/owenchan1987/article/details/77688484
断点续传的实现
五)并发编程有关知识点
(这个是一般Android开发用的少的,所以建议多去看看):
平时Android开发中对并发编程可以做得比较少,Thread这个类经常会用到,但是我们想提升自己的话,一定不能停留在表面,,我们也应该去了解一下java的关于线程相关的源码级别的东西。
学习的参考资料如下:
Java 内存模型
java线程安全总结
http://www.iteye.com/topic/806990
深入理解java内存模型系列文章
http://ifeve.com/java-memory-model-0/
线程状态:
一张图让你看懂JAVA线程间的状态转换
https://my.oschina.net/mingdongcheng/blog/139263
锁:
锁机制:synchronized、Lock、Condition
http://blog.youkuaiyun.com/vking_wang/article/details/9952063
Java 中的锁
http://wiki.jikexueyuan.com/project/java-concurrent/locks-in-java.html
并发编程:
Java并发编程:Thread类的使用
http://www.cnblogs.com/dolphin0520/p/3920357.html
Java多线程编程总结
http://blog.51cto.com/lavasoft/27069
Java并发编程的总结与思考
https://www.jianshu.com/p/053943a425c3#
Java并发编程实战—–synchronized
http://www.cnblogs.com/chenssy/p/4701027.html
深入分析ConcurrentHashMap
http://www.infoq.com/cn/articles/ConcurrentHashMap#