java--多线程

来源:互联网 发布:淘宝数据分析网站 编辑:程序博客网 时间:2024/05/21 12:41

java--多线程

本文仅属个人浅谈,不正确的地方敬请批评指正

要了解线程,不可或缺的你也得知道何为进程,拿手机操作系统为例,进程就是手机上的一款应用,他们生来系统就会分配给他们一定的空间,手机可以同时打开几个应用,这就是多进程;一个应用呢可以同时打开多个任务,比如说一个下载的应用可以同时进行多个下载任务,每个任务就是一个线程(单核),这样的同时下载就是多线程并发;说到多线程并发呢,大家要区分他与并行的区别,并行是指多个线程同时进行,并发指多个线程同时进行,但某个时刻点只有一个线程在运行 ,由于系统CPU运行速度很快,以至于大家认为是同时进行的。现在这个多核的时代通常多线程并发和并行可能都存在,就看系统怎么去调度了……

说了这多个人见解,下面进入代码世界,之前唠叨的有问题的地方敬请批评指正

创建线程 :通常有两种方法  继承Thread类和实现Runnable接口

方法一 、继承Thread类并重写run()方法

class MyThread  extends Thread{

int i = 0;
@Override
public void run() {
super.run();
for (; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"---->"+i);
}
}

}

public class Test1 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+i);
if (i==5) {
new MyThread().start();
new MyThread().start();
}
}
}
}

运行结果:

main0
main1
main2
main3
main4
main5
main6
main7
Thread-0---->0
main8
Thread-1---->0
main9
Thread-0---->1
Thread-0---->2
Thread-0---->3
Thread-1---->1
Thread-0---->4
Thread-1---->2
Thread-1---->3
Thread-0---->5
Thread-1---->4
Thread-0---->6
Thread-1---->5
Thread-0---->7
Thread-1---->6
Thread-0---->8
Thread-1---->7
Thread-0---->9
Thread-1---->8
Thread-1---->9

每次的结果都会不一样,这只是其中一种

方法二、

public class MyRunable implements Runnable{
int i = 0;
@Override
public void run() {
for (; i < 50; i++) {
System.out.println(Thread.currentThread().getName()+"---->"+i);
}
}
}

public class Test {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+i);
if (i==5) {
MyRunable my = new MyRunable();
new Thread(my,"线程A").start();
new Thread(my,"线程B").start();
}
}
}
}

运行结果:

main0
main1
main2
main3
main4
main5
main6
线程A---->0
线程B---->0
main7
线程B---->2
线程A---->1
线程A---->4
线程A---->5
线程A---->6
线程B---->3
main8
main9
线程B---->8
线程B---->9
线程A---->7

发现和方法一有明显区别:

首先看清我是把变量声明在方法外,方法一两个线程各自输出自己的变量0-9;方法二是两个线程共同输出0-9,(当然里面会有些问题,咱后面线程锁会讲到)也就是说方法二共享了变量。

 两种实现方式的区别和联系:

在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比

继承Thread类有如下好处:

->避免点继承的局限,一个类可以继承多个接口。

->适合于资源的共享

在以经典例子卖票为例分别在用两种发法写一下:

通过Thread类完成:
class MyThread1 extends Thread {
private int ticket = 10;
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
for (int i = 0; i < 20; i++) {
if (this.ticket > 0) {
System.out.println("卖票:ticket" + this.ticket--);
}
}
}
}

public class ThreadTicket {
public static void main(String[] args) {
MyThread1 mt1 = new MyThread1();
MyThread1 mt2 = new MyThread1();
MyThread1 mt3 = new MyThread1();
mt1.start();
mt2.start();
mt3.start();
}
}

运行结果:

卖票:ticket10
卖票:ticket10
卖票:ticket10
卖票:ticket9
卖票:ticket9
卖票:ticket8
卖票:ticket9
卖票:ticket7
卖票:ticket8
卖票:ticket6
卖票:ticket8
卖票:ticket7
卖票:ticket6
卖票:ticket5
卖票:ticket4
卖票:ticket3
卖票:ticket2
卖票:ticket1
卖票:ticket5
每个线程都各卖了10张,共卖了30张票;但实际只有10张票,每个线程都卖自己的票,没有达到资源共享

//如果用Runnable就可以实现资源共享,下面看例子:
class MyThread2 implements Runnable {
private int ticket = 10;
public void run() {
for (int i = 0; i < 20; i++) {
if (this.ticket > 0) {
System.out.println("卖票:ticket" + this.ticket--);
}
}
}
}
public class ThreadTicket {
public static void main(String[] args) {
MyThread2 mt = new MyThread2();
new Thread(mt).start();// 同一个mt,但是在Thread中就不可以,如果用同一
new Thread(mt).start();// 个实例化对象mt,就会出现异常
new Thread(mt).start();
}
};

运行结果:

卖票:ticket10
卖票:ticket9
卖票:ticket7
卖票:ticket6
卖票:ticket8
卖票:ticket5
卖票:ticket4
卖票:ticket2
卖票:ticket3
卖票:ticket1

这两种方法本人建议使用第二种;

接着讲,不知道大家在用第二种方法资源共享时有没有发现有时候也会出问题,就那上面卖票的例子,会出现两个线程同时买同一张票的情况,以下就是我运行多次出现的结果……

卖票:ticket9
卖票:ticket10
卖票:ticket10
卖票:ticket7
卖票:ticket6
卖票:ticket8
卖票:ticket4
卖票:ticket5
卖票:ticket1
卖票:ticket2
卖票:ticket3

解决这问题就要设计到了线程安全,引出一个知识点 线程锁synchronized;

接着以卖票为例,只能一个线程一个线程来,上一个线程没完成之前下一个线程就等着,避免混乱。出现两个线程拥有两个相同的票;

代码:

class MyThread2 implements Runnable {
private int ticket = 10;
public void run() {
for (int i = 0; i < 20; i++) {
saleTicket();
}
}
public synchronized void saleTicket() {
if (this.ticket > 0) {
System.out.println("卖票:ticket" + this.ticket--);
}
}
}
public class ThreadTicket {
public static void main(String[] args) {
MyThread2 mt = new MyThread2();
new Thread(mt).start();// 同一个mt,但是在Thread中就不可以,如果用同一
new Thread(mt).start();// 个实例化对象mt,就会出现异常
new Thread(mt).start();
}
};

运行结果:

卖票:ticket10
卖票:ticket9
卖票:ticket8
卖票:ticket7
卖票:ticket6
卖票:ticket5
卖票:ticket4
卖票:ticket3
卖票:ticket2
卖票:ticket1

这样线程就安全了,运行几次都不会出现意外哦……

1 0