在学习多线程之前,有必要了解一下什么是进程,什么是线程,以及两者之间的区别。
进程:运行中的应用程序称为进程,拥有系统资源(cpu,内存)。
线程:进程中的程序片段,一个进程可以有多个程序片段,线程本身不单独享有资源(共享所在进程的资源)。
进程和线程的区别:
1.是否占有资源
2.创建或者撤销一个进程所需要的开销比创建或者撤销一个线程所需要的开支大
3.进程是轻量级组件,进程是重量级组件。
并行和并发的区别:
并行:两个任务同时执行,就是甲任务执行的同时,乙任务也在执行(需要多核cpu)。
并发:是指两个任务都请求运行,而处理器只能接受一个任务,就把这两个任务安排轮流执行,由于时间间隔较短,使人感觉到这两个任务都在同时运行。其实,真正意义上的同时是不存在的。只是由于cpu运行速度太快了。
Java里是多线程的,至少启动了主线程和垃圾回收线程。
Java里实现多线程有两种方式:
1.继承Thread类
class Te extends Thread{
@Override
public void run() {
super.run();
for(int i=0;i<10;i++) {
System.out.println(i+"这是继承Thread接口 体现多线程的一种方式");
}
}
}
public static void main(String[] args) {
Te t=new Te();
t.start();
for(int i=0;i<10;i++) {
System.out.println("主线程");
}
}
2.实现Runnable接口
class RunnableImpl implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++) {
System.out.println("这是实现Runnable接口的 体现多线程的一种方式");
}
}
public static void main(String[] args) {
RunnableImpl runnableImpl=new RunnableImpl();
Thread thread=new Thread(runnableImpl);
thread.start();
for(int i=0;i<10;i++) {
System.out.println("主线程");
}
}
继承Thread:
好处:可以直接使用Thread类中的方法,代码简单。
弊端:如果有了父类,就不能用这种方法。毕竟Java是单继承机制。
实现Runnable接口
好处:即使定义的线程有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的。并且可以共享资源。
弊端:不能直接使用Thread中的方法,需要先获取到线程对象后,才可以得到Thread的方法,代码复杂。
匿名内部类实现多线程的两种方式
1.继承Thread类
new Thread() {
public void run() {
System.out.println("匿名内部类实现线程");
};
}.start();
2.实现Runnable接口
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类实现线程二");
}
}) {
}.start();
获取当前线程的名字 设置名字
new Thread("adasd") {//可以通过构造函数传入一个字符串进行设置名字
public void run() {
//Thread.currentThread() 获取当前线程的对象
//Thread.currentThread().getName() 获取当前线程对象的名字
System.out.println(Thread.currentThread().getName());
System.out.println("匿名内部类实现线程");
};
}.start();
线程里一些常用的方法:
1.sleep(毫秒,纳秒);控制当前线程休眠若干毫秒
class Te extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 10; i++) {
if(i==5) {
try {
Thread.sleep(5000);//休眠5秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "这是继承Thread接口 体现多线程的一种方式");
}
}
}
2.join();当前线程暂停,等待指定的线程执行结束后,当前线程再继续。也可以传入一个毫秒数,等待制定的毫秒数再继续。
public class Test04 {
public static void main(String[] args) {
Thread t=new Thread() {
public void run() {
for(int i=0;i<500;i++) {
System.out.println(i+"线程1");
}
};
};
Thread t2=new Thread() {
public void run() {
for(int i=0;i<50;i++) {
if(i==10) {
try {
//t.join();
t.join(1);//插队指定的时间,过了指定时间,两条线程交替执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+"线程2");
}
};
};
t.start();
t2.start();
}
}
3.yield();礼让线程,让出cpu 让其他线程先执行
4.设置线程的优先级
优先级越高的线程被线程调度器的几率就越高,Java中线程优先级的设定是通过setPriority(int leve),优先级是[1,10]之间的一个整数,在线程运行中会其一定的作用,但是作用不大。
t.setPriority(1);
t2.setPriority(10);
t.setPriority(Thread.MAX_PRIORITY);//设置最大的线程优先级
t.setPriority(Thread.MIN_PRIORITY);//设置最小的线程优先级