JAVA 10(多线程)

创建线程:

通过对java.lang包的查找,继承Thread类可以创建线程

1,建立类继承Thread类

2,复写Thread中的ran方法。

3,调用线程的start()方法,该方法的作用是,启动线程,调用ran方法。

public class Test {

public static void main(String args[])

{

Demo a= new Demo();

a.start();

for(int x=0;x<=100;x++)

System.out.println("hello word");

}

}

class Demo extends Thread

{

public void ran()

{

for(int x=0;x<=100;x++)

System.out.println("Demo ran");

}

}

两个输出会交替出现。

发现运行结果每次都不同

因为多个线程都在获取cpu的使用权,cpu执行到谁,谁就运行,在某一时刻,只能有一个程序在运行(多核除外)cpu在做着快速切换,已达到看上去是在同时运行。

多线程特性:随机性,谁抢到谁执行,至于执行多长时间,cpu说的算。

为什么要覆盖ran方法

thread类用于描述线程。

该类定义了用于存储要运行的代码,这些代码就存储在ran方法中。

ran() 和 start() 区别

只写ran()线程没有被创建,编程了单线程程序。会顺序执行,输出不是随机的。

 

线程运行过程中的状态:

线程对象的名称:

每个线程都有默认名称。

Thread-编号   //该编号从0开始

线程名称可以提供 线程.getName()  方法获得

currentThread() :获取当前运行的线程对象

getName():获取线程名称

买票程序举例:

public class Test

{

public static void main(String args [])

{

Ticket t1 = new Ticket();

Ticket t2 = new Ticket();

Ticket t3 = new Ticket();

Ticket t4 = new Ticket();

Ticket t5 = new Ticket();

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

}

}

class Ticket extends Thread

{

private static int tick=100; //静态,所有对象公用一个票数。

public void run()

{

if(tick>0)

System.out.println(currentThread().getName()+"sale:"+tick--);

}

}

第二种创建进程的方法

 

实现runable接口

步骤:

1,定义类,实现runnable接口

2,覆盖runnable中的run()方法

3,通过Thread;类建立线程对象

4,将Runnable接口对象作为实际参数传递给Thread类的构造函数

5,调用Thread类的start方法开启线程并调用Runnable子类中的run方法

实现方式和前一种方法的区别:

实现方式好处在于:避免了单继承的局限性。

在定义线程时,建议使用实现方式。

继承Thread类:线程代码存放在Thread子类对象run方法中

实现Runnable:线程代码存放在接口的子类对象的run中

在此例中ticket也不用static了,因为只建立了一个对象

睡眠:

try

{Thread.sleep(10);}

catch(Exception e)

{

}

public class Test

{

public static void main(String args [])

{

Ticket t = new Ticket();

Thread t1 =new Thread(t);

Thread t2 =new Thread(t);

Thread t3 =new Thread(t);

Thread t4 =new Thread(t);

t1.start();

t2.start();

t3.start();

t4.start();

}

}

class Ticket implements Runnable

{

private int tick = 100;

public void run()

{

while(true)

if(tick>0)

{

System.out.println("sale"+tick--);

}

}

}

安全问题:

以下代码会打印  0,-1,-2号票

产生问题原因:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,另一个线程1参与进来执行,导致共享数据出现错误。

解决办法:对多条操作共享数据的语句,只能让让一个线程都执行完,在执行过程中,其他线程不可以参与执行。

java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。会保证该代码块内的代码被全部执行再切换线程。

格式:

synchronized(对象)

{

需要被同步的代码

}

public class Test

{

public static void main(String args [])

{

Ticket t = new Ticket();

Thread t1 =new Thread(t);

Thread t2 =new Thread(t);

Thread t3 =new Thread(t);

Thread t4 =new Thread(t);

t1.start();

t2.start();

t3.start();

t4.start();

}

}

class Ticket implements Runnable

{

private int tick = 100;

public void run()

{

while(true)

if(tick>0)

{

try

{Thread.sleep(10);}

catch(Exception e)

{

}

System.out.println("sale"+tick--);

}

}

}

修改安全问题后的代码

public class Test

{

public static void main(String args [])

{

Ticket t = new Ticket();

Thread t1 =new Thread(t);

Thread t2 =new Thread(t);

Thread t3 =new Thread(t);

Thread t4 =new Thread(t);

t1.start();

t2.start();

t3.start();

t4.start();

}

}

class Ticket implements Runnable

{

Object obj= new Object();

private int tick = 100;

public void run()

{

while(true)

{

synchronized(obj)

{

if(tick>0)

{

try

{Thread.sleep(10);}

catch(Exception e)

{

}

System.out.println("sale"+tick--);

}

}

}

}

}

如何找到安全问题/同步的前提:

1,明确哪些代码是多线程运行的代码。

2,明确共享数据。

3,明确多线程代码中哪些语句是操作共享数据的。

同步函数:

同步有两种,1代码块,2同步函数

用synchronized修饰函数即可。

同步代码块使用的锁时obj

同步函数的锁:

同步函数使用的所时this  也就是调用该函数的实体。

如果同步函数被静态修饰后,使用的锁是该类对应的class,就是类名点class 。   Ticket.class

懒汉式

死锁:

 

两个锁:

同步中嵌套同步,锁却不同,恰好停止在某位置,会造成死锁。

要避免死锁。

public class Test

{

public static void main(String args [])

{

Thread t1 = new Thread(new Deadlock(true));

Thread t2 = new Thread(new Deadlock(false));

t1.start();

t2.start();

}

}

class Deadlock implements Runnable

{

private boolean flag;

Deadlock(boolean flag)

{

this.flag = flag;

}

public void run()

{

if(flag)

{

while(true)

{

synchronized(Mylock.locka)

{

System.out.println("if lock a");

synchronized(Mylock.lockb)

{

System.out.println("if lockb");

}

}

}

}

else

{

while(true)

{

synchronized(Mylock.lockb)

{

System.out.println("else lockb");

synchronized(Mylock.locka)

{

System.out.println("else locka");

}

}

}

}

}

}

class Mylock

{

static Object locka = new Object();

static Object lockb = new Object();

}

时间: 2024-10-10 13:19:37

JAVA 10(多线程)的相关文章

Java基础--多线程的方方面面

1,什么是线程?线程和进程的区别是什么? 2,什么是多线程?为什么设计多线程? 3,Java种多线程的实现方式是什么?有什么区别? 4,线程的状态控制有哪些方法? 5,线程安全.死锁和生产者--消费者 6,线程的优化有哪些方法? 1,什么是线程?线程和进程的区别是什么? 线程是程序执行的最小单元. 区别: 进程是操作系统进行资源处理和分配的最小单位,而一个进程可以包含多个线程,并共享进程的资源. 2,什么是多线程?为什么设计多线程? 介绍之前,我们需要理解并行和并发的定义: 并行:同一个时刻有多

java实现多线程下载

本篇博客可认为是对 使用java实现http多线程下载 一文的再次解读. 首先,从宏观来说 java实现多线程下载这个功能的实现由以下几部分组成: 1 建立多个线程去分别下载文件的一部分. 2 将多个线程下载的文件(还在内存中),写入硬盘中的一个文件. 3 断点续传 GET /Path/FileName HTTP/1.0 Host: www.server.com:80 Accept: */* User-Agent: GeneralDownloadApplication Connection: c

Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)

一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专家又往往建议我们远离它.比如Thread这个很基础的类,其中很重要的线程状态字段,就是用volatile来修饰,见代码 /* Java thread status for tools, * initialized to indicate thread 'not yet started' */   p

Java入门——多线程(二)

Java入门——多线程(二) 线程的状态 要想实现多线程,必须在主线程中创建新的线程对象.任何线程一般具有5种状态. 创建状态:用构造方法创建一个线程对象之后,新的线程就处于该状态.已经有了相应的内存空间和其他资源和其他资源. 就绪状态:线程进入线程队列排队,等待CPU服务. 运行状态:CPU处理,自动调用run()方法. 阻塞状态:就是在执行过程中暂时挂起.原因有:人为挂起,CPU的决定,sleep(),suspend(),wait()等方法.只有当引起阻塞的原因被消除后,线程才能转入就绪状态

黑马程序员——java基础——多线程

 黑马程序员--java基础--多线程 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行.一个进程中至少有一个线程. 一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区.自己的变量.

JAVA:认识多线程

以前古老的DOS操作系统是单任务的,还没有线程的概念,系统在每次只能做一件事情.比如你在copy东西的时候不能rename文件名.为了提高系统的利用效率,采用批处理来批量执行任务. 现在的操作系统都是多任务操作系统,每个运行的任务就是操作系统所做的一件事情,比如你在听歌的同时还在用MSN和好友聊天.听歌和聊天就是两个任务,这个两个任务是"同时"进行的.一个任务一般对应一个进程,也可能包含好几个进程.比如运行的MSN就对应一个MSN的进程,如果你用的是windows系统,你就可以在任务管

使用Java开发多线程端口扫描工具(二)

一 介绍 这一篇文章是紧接着上一篇文章(http://www.zifangsky.cn/2015/12/使用java开发多线程端口扫描工具/)写的,端口扫描的原理不用多少,我在上一篇文章中已经说过了,至于目的大家都懂得.在这一篇文章里,我主要是对端口扫描工具的继续完善,以及写出一个比较直观的图形界面出来,以方便我们测试使用.界面如下: 这个工具主要是实现了以下几点功能:(1)两种扫描方式,一种是只扫描常见端口,另一种是设置一个起始和结束端口,依次探测.当然,原理很简单,用for循环就可以了:(2

Java基础-多线程-③多线程的同步之synchronized

使用线程同步解决多线程安全问题 上一篇 Java基础-多线程-②多线程的安全问题 中我们说到多线程可能引发的安全问题,原因在于多个线程共享了数据,且一个线程在操作(多为写操作)数据的过程中,另一个线程也对数据进行了操作,从而导致数据出错.由此我们想到一个解决的思路:将操作共享数据的代码行作为一个整体,同一时间只允许一个线程执行,执行过程中其他线程不能参与执行.线程同步就是用来实现这样的机制. synchronized代码块 Java中提供了synchronized关键字,将可能引发安全问题的代码

Java基础-多线程-②多线程的安全问题

什么是线程的安全问题? 上一篇 Java基础-多线程-①线程的创建和启动 我们说使用实现Runnable接口的方式来创建线程,可以实现多个线程共享资源: 1 class Dog implements Runnable { 2 // 定义线程共享数据 3 private int t = 100; 4 5 @Override 6 public void run() { 7 // TODO:死循环,暂不处理 8 while (true) { 9 if (t > 0) { 10 11 System.ou