一、多线程的实现方式
1、继承Thread类
Thread t2 = new Thread(){
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
while(true){
System.out.println(Thread.currentThread().getName());
}
}
};
t2.start();
2、实现Runnable接口
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
while(true){
System.out.println(Thread.currentThread().getName());
}
}
}).start();
使用Lambda表达式重写
new Thread(()->{//用lambda表达式代替
while(true){
System.out.println(Thread.currentThread().getName());
}
}).start();
- 注意:多线程机制不会提高程序的运行效率,之所以用多线程下载,是为了抢服务器的带宽
3、面试题
//面试题:会实现Thread里面的方法还是Runnable里面的方法?
new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println("Runnable "+Thread.currentThread().getName());
}
}
}){
@Override
public void run() {
while(true){
System.out.println("Thread "+Thread.currentThread().getName());
}
}
}.start();
//会先在子类中找方法,若子类没有,在输出参数任务中的runnable run,若都没有,则执行Thread类中默认的run()方法。
4、练习:
需求:设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1
思路:将两个runnable作为内部类,要共享的数据作为外部类的成员变量
public class MultiThreadShareData {
private int j;
public static void main(String[] args) {
MultiThreadShareData mt = new MultiThreadShareData();
for(int i = 0;i<2;i++){
new Thread(mt.new Inc()).start();
new Thread(mt.new Dec()).start();
}
}
//两个方法为同一个锁对象,this
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+" inc " +j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+" dec " +j);
}
class Inc implements Runnable{
@Override
public void run() {
for(int i = 0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
@Override
public void run() {
for(int i = 0;i<100;i++){
dec();
}
}
}
}
5、实现Runnable接口比继承Thread类所具有的优势:
1.适合多个相同的程序代码的线程去共享同一个资源。
2. 可以避免java中的单继承的局限性。
3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和数据独立。
4. 线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
5.实现Runnable接口,更能体现面向对象的概念,执行体放在Runnable的实现类中
二、线程同步通信技术
需求:主线程执行100次,子线程执行10次,交替执行,共循环50次
public class TranditionCommunication {
public static void main(String[] args) {
//或直接将内部类改为静态内部类则可以直接创建内部类的实例对象
final Business business = new TranditionCommunication().new Business();
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0;i<50;i++){
business.sub(i);
}
}
}).start();
for(int i = 0;i<50;i++){
business.main(i);
}
}
//内部类
class Business{
boolean isSub = true;
public synchronized void sub(int i){
while(!isSub){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0;j<10;j++){
System.out.println("sub method "+j+" loop of "+i);
}
isSub = false;
this.notify();
}
public synchronized void main(int i){
while(isSub){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0;j<100;j++){
System.out.println("main method "+j+" loop of "+i);
}
isSub = true;
this.notify();
}
}
}
- this.notify与 this.wait()需要与synchronized的锁对象一致,synchronized写在方法上则也是用this实现互斥
三、定时器
需求:第一次在2s后发生,第二次在4s,后面又是2s,交替进行
public class TranditionalTimerTest {
static int count = 0;
public static void main(String[] args) {
class MyTimerTask extends TimerTask{
@Override
public void run() {
count ++;
count = count % 2;
System.out.println("bombing!");
new Timer().schedule(new MyTimerTask(),2000+2000*count);
}
}
new Timer().schedule(new MyTimerTask(),2000);
// new Timer().schedule(new TimerTask() {
// @Override
// public void run() {
// System.out.println("bombing!");
// }
// },5000,3000);//第一次在5s后发生,后面每隔3次发生一次
//
while(true){
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}