Java多线程(一)

## 多线程

### 1.程序、进程、线程

- 在操作系统中运行的程序就是进程;

- 一个进程可以有多个线程;
- 程序是指令和数据的有序集合,是一个静态的概念;
- 而进程则是执行程序的一次执行过程,是一个动态的概念;
- 进程是系统资源分配的单位
- 线程是CPU调度和执行的单位
- 真正的多线程是指多个cpu,即多核

理解:进程相当于一个类,类中有多个方法(即多个线程),main()方法即(主线程),gc线程。

- main()方法即(主线程)为系统的入口,用于执行整个程序;
- 线程的运行是由调度器安排调度,不能人为干预;
- 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制
- 线程会带来额外的开销,如cpu的调度时间,并发控制开销
- 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

### 2.线程的创建

1. **三种创建方式**

- Thread class

- 继承Thread类

- Runnable接口

- 实现Runnable接口

- Callable接口

- 实现Callable接口

 

### **3.Thread**

- 自定义类继承Thread
- 重写run()方法;
- 创建对象,调用start()开启线程

```java
import javax.xml.transform.Source;

public class TestThread01 extends Thread{
//继承Thread类
//总结:线程开启不一定立即执行,有CPU调度执行

@Override
public void run() {
//run()方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("**********-4564646465");
}
}

//main线程,即主线程
public static void main(String[] args) {

TestThread01 testThread01 = new TestThread01();

//testThread01.start();//线程开启,交替(类似同时)执行,电脑单核只有一个cpu

testThread01.run();//这个在前,先执行run();

for (int i = 0; i < 20; i++) {
System.out.println("7554574545*********");
}

}


}

```

多线程实现多张图片同时下载

```java
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

public class TestThread02 extends Thread{
private String url;
private String name;

public TestThread02(String url,String name){
this.url=url;
this.name=name;
}
public TestThread02(){
}

@Override
public void run() {
//下载线程
WebDownloader webDownloader = new WebDownloader();
try {
webDownloader.downloader(url,name);
System.out.println(name);
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
TestThread02 testThread02 = new TestThread02("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603037822768&di=5f0cc79b7c104781de8cea48c7d8b1ca&imgtype=0&src=http%3A%2F%2Fattach.bbs.miui.com%2Fforum%2Fmonth_1012%2F10120514509c7244b23f4a2fa5.jpg","a.jpg");
TestThread02 testThread03 = new TestThread02("https://ns-strategy.cdn.bcebos.com/ns-strategy/upload/fc_big_pic/part-00720-1746.jpg","a1.jpg");
TestThread02 testThread04 = new TestThread02("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2441956749,4275399915&fm=26&gp=0.jpg","a2.jpg");
testThread02.start();
testThread03.start();
testThread04.start();
}

}
//下载器
class WebDownloader{
//下载方法
public void downloader(String url,String name) throws IOException {

FileUtils.copyURLToFile(new URL(url),new File(name));

}
}

```

### 4.Runnable

推荐使用Runnable对象,因为Java单继承的局限性

1. 定义MyRunnable类实现Runnable接口
2. 实现run()方法,编写线程执行体
3. 创建线程对象,调用start()方法启动线程

```java
public class TestRunnable01 implements Runnable{

public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("*******************");
}
}

public static void main(String[] args) {
TestRunnable01 testRunnable01 = new TestRunnable01();
new Thread(testRunnable01).start();
}
}

```

### 5.小结

- 继承Thread
- 子类继承Thread类具备多线程能力
- 启动线程:子类对象.start()
- 不建议使用:避免OOP单继承局限性

- 实现Runnable接口
- 实现接口Runnable具备多线程能力
- 启动线程:传入目标对象+Thread对象。start()
- 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

![](https://oscimg.oschina.net/oscnet/up-f5ed8c0ddedcef86a8731c9e51a511d3753.png)

**多个线程操作同一个资源问题**

```java
//多个线程操作同一个资源
//模拟买票

//发现问题:多个线程操作同一个人资源的情况下,线程不安全,数据紊乱。

public class TestRunnable02 implements Runnable{

private int ticket=10;


public void run() {
while (true){
if (ticket<=0){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticket--+"票");

}
}

public static void main(String[] args) {
TestRunnable02 runnable02=new TestRunnable02();
new Thread(runnable02,"小鹏").start();
new Thread(runnable02,"小强").start();
new Thread(runnable02,"小慧").start();
}
}
```

### **6.实例:龟兔赛跑**

```java
import org.omg.Messaging.SyncScopeHelper;

public class Race implements Runnable{

private static String winner;


public void run() {
for (int i = 0; i <= 100; i++) {

//模拟兔子睡觉
if (Thread.currentThread().getName().equals("兔子")&&i%50==0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

//判断100步
if (win(i)){
break;
}
System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
}
}

//判断胜利者
public boolean win(int step){
if (winner!=null){
return true;
}
if (step>=100){
winner=Thread.currentThread().getName();
System.out.println("胜利者是"+winner);

}

return false;
}

public static void main(String[] args) {
Race race=new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
```

### 7.Callable

![](https://oscimg.oschina.net/oscnet/up-c5b8f65c08d3f7474f74aa787bad876d3ff.png)

posted @ 2020-10-18 23:17  V587h  阅读(70)  评论(0)    收藏  举报