多线程的目的
多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
并发和并行
并发: 提高单处理器上的程序运行效率
并行: 多个cpu.
线程 和 进程
一条线程指的是进程中一个单一顺序的控制流
一个进程中可以并发多个线程,每条线程并行执行不同的任务。
进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
java 实现多线程的三个方式
(前两个是Java1.8版本之前用的,Java1.8版本及之后三个都可以用)
通过实现 Runnable 接口;
通过继承 Thread 类本身;
通过 Callable 和 Future 创建线程。
1、线程会互抢资源的
package thread;
public class Demo1 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("run方法里面就是一个线程需要执行的任务");
for(int i=0;i<200;i++){
System.out.println("********demo1运行");
}
}
}
package thread;
public class Demo2 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("run方法里面就是一个线程需要执行的任务");
for(int i=0;i<200;i++){
System.out.println("@@@@@@@@@@@**demo2运行");
}
}
}
Test
package thread;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo1 demo1=new Demo1();
//创建一个线程
Thread t1=new Thread(demo1);
// 启动一个线程是执行start方法,执行内容是run方法里执行
t1.start();
Demo2 demo2=new Demo2();
Thread t2=new Thread(demo2);
t2.start();
}
}
结果
run方法里面就是一个线程需要执行的任务
********demo1运行
********demo1运行
********demo1运行
********demo1运行
run方法里面就是一个线程需要执行的任务
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
********demo1运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
@@@@@@@@@@@**demo2运行
********demo1运行
...
2、线程休眠
package thread;
import java.util.Date;
public class Demo3 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
try {
//线程休眠3秒后执行(可用于倒计时)
System.out.println("开始"+new Date());
Thread.sleep(3000);
System.out.println("结束"+new Date());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Test
package thread;
public class Test1 {
public static void main(String[] args) {
Demo3 demo3=new Demo3();
Thread t3=new Thread(demo3);
t3.start();
}
}
结果
3、线程不安全问题
package thread;
public class Task {
int total=600;
int runtime=0;
public void finishtask(){
this.total--;
runtime++;
System.out.println("total="+total+"***runtime="+runtime);
}
}
package thread;
public class Demo4 implements Runnable{
Task task;
public Demo4(Task task){
this.task=task;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<300;i++){
this.task.finishtask();
}
}
}
package thread;
public class Demo5 implements Runnable{
Task task;
public Demo5(Task task){
this.task=task;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<300;i++){
this.task.finishtask();
}
}
}
test
package thread;
public class Test1 {
public static void main(String[] args) {
Task task=new Task();
Demo4 demo4=new Demo4(task);
Thread t4=new Thread(demo4);
t4.start();
Demo5 demo5=new Demo5(task);
Thread t5=new Thread(demo5);
t5.start();
System.out.println("执行次数"+task.runtime);
System.out.println("执行总数"+task.total);
}
}
结果