java 多线程(一)
介绍
并行:一起行走,在一段时间内发生。
并发:同时发生,在某一刻时间完成。
进程:
一个进程也即一个任务
window和linux都是多任务操作系统
进程与进程之间是相互独立的
线程:
一个进程可以有多个线程,至少有一个线程
一个线程代表时间上的线性顺序执行
线程是CPU划分资源的最小单位(时间片和内存)
一个进程下的线程可以资源共享
单核:cpu是通过划分时间片来实现多线程,实际上是并行
多核:cpu可以并发实现多线程
对于程序员来说,Java平台和操作系统屏蔽了单核与多核问题。
多线程编程,一般来说解决两个问题:速度和设计可管理性。方法是并发(或者在单核cpu上通过并行模拟)实现,所以也称为并发编程,引发的问题称为并发问题。
(1)更快的执行
将一个程序分为多个片段,分别执行。
多核:web服务器常见,实际上现在一般的电脑都是多核了。并发执行,理所当然的更快了。
单核:一般来说,这种情况下任务整体的顺序执行应该要快于分片的并行执行,因为需要考虑到上下文切换的消耗。但如果任务中包含阻塞情况,通常是I/O,而导致程序停止下来等待外部条件的变化,那么多线程就会提高速度。
事实上,从性能角度来看,没有任务会阻塞,那么在单处理器上使用多线程就没有任何意义。(但目前多核更常见)
(2)设计可管理性
GUI和WEB环境(比如Servlet)
创建
1、继承Thread类
public class demo01 {
public static void main(String[] args) {
Dog dog = new Dog("小白");
Dog dog2 = new Dog("小黑");
dog.start();
dog2.start();
}
}
class Dog extends Thread{
int count = 0;
String name;
public Dog(){}
public Dog(String name){this.name = name;}
@Override
public void run(){
while(++count<101) {
System.out.println(name+"跑了:" +count + "米");
}
}
}
2、实现Runnable接口
public class demo02 {
public static void main(String[] args) {
Cat cat1 = new Cat("小红");
Cat cat2 = new Cat("小绿");
Thread t1 = new Thread(cat1);
Thread t2 = new Thread(cat2);
t1.start();
t2.start();
}
}
class Cat implements Runnable{
int count = 0;
String name;
public Cat(){}
public Cat(String name){this.name = name;}
@Override
public void run(){
while(++count<101) {
System.out.println(name+"跑了:" +count + "米");
}
}
}
3、执行器Executor
public class Test03 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Cat("小红"));
executorService.execute(new Cat("小绿"));
executorService.shutdown();
}
}
4、通过Callable和FutureTask
public class Test04 {
public static void main(String[] args) {
A a = new A();
FutureTask<Integer> ft = new FutureTask<>(a);
for(int i = 0;i < 100;i++)
{
System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);
if(i==20)
{
new Thread(ft,"有返回值的线程").start();
}
}
try
{
System.out.println("子线程的返回值:"+ft.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class A implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int i = 0;
for(;i<100;i++)
{
System.out.println(Thread.currentThread().getName()+" "+i);
}
return i;
}
}