黑马程序员_java多线程(1)
来源:互联网 发布:倩女手游 mac 编辑:程序博客网 时间:2024/05/02 04:32
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
多线程
进程:是一个正在执行中的程序,每一个进程执行都有一个顺序,该顺序是一个执行路径.或者叫一个控制单元.
线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行.
一个进程中至少有一个线程.
Java VM 启动的时候会有一个进程,java.exe.该进程中至少一个线程负责java程序的执行.而且这个线程运行的代码存在于main方法中.该线程称之为主线程.
扩展知识:Java VM 启动时有两个线程,一个是主线程,另一个是垃圾回收机制线程.(例如,下载程序是多线程.)
意义:多线程的出现使多个程序同时执行,提高效率.
如何在自定义的代码中自定义一个线程?
创建线程的第一种方式:
继承Thread类.
复写Thread类中的run方法.
目的:将自定义代码存储在run方法中,让线程运行.
调用线程的start方法.该方法的两个作用:
1启动线程
2调用run方法
例题
class Demo extends Thread{
public void run(){
System.out.println(“Demo run”)
}
}
Class ThreadDemo{
Public static void main(string args[]){
Demo D = new Demo();
创建一个线程
D.start();
}
}
与调用run方法的区别?
class Demo extends Thread{
public void run(){
for(int x = 0; x< 60;x++)
System.out.println(“Demo run” + x)
}
}
Class ThreadDemo{
Public static void main(string args[]){
Demo D = new Demo();
D.start();
For(int x = 0; x < 60; x++)
System.out.println(“Hello” + x)
}
}
Main执行hello,D.start执行Demo.形成了多线程.在ThreadDemo中有两个执行路径,在真实情况下是绝对不可能同时执行的(除非双核即双CPU).因为CPU切换的极快.
发现运行结果每一次都不同,因为多个线程都获取CPU的执行权,CPU执行的谁,谁就运行谁.其实这就是多线程的随机性.
为什么要覆盖run方法呢?
Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法.也就是说Thread类中的run方法,用于存储线程要运行的代码.
若Class ThreadDemo{
Public static void main(string args[]){
Thread t = new Thread();
T.start();
}
}
运行结果:没有任何结果.因为run()的()中没有任何东西.
若Class ThreadDemo{
Public static void main(string args[]){
Demo D = new Demo();
D.start();
开启线程并执行线程的run方法.
D.run();
仅仅是对象调用.
}
}
例题:创建两个线程与主线程交替运行?
class Demo extends Thread{
private String name;
Demo(String name){
this.name = name;
}
public void run(){
for(int x = 0; x< 60;x++){
System.out.println(name + “Demo run” + x)
}
}
}
Class ThreadDemo{
Public static void main(string args[]){
Demo D = new Demo(“one”);
Demo D1 = new Demo(“two”);
D.start();
D1.start();
for(int x = 0; x< 60;x++)
System.out.println(“Demo run” + x)
}
}
获取多线程的对象及其名称.(getName()或者Thread.currdntThread())
class Demo extends Thread{
private String name;
Demo(String name){
this.name = name;
}
public void run(){
for(int x = 0; x< 60;x++){
System.out.println(this.getName() + “Demo run” + x)
}
}
}
Class ThreadDemo{
Public static void main(string args[]){
Demo D = new Demo(“one”);
Demo D1 = new Demo(“two”);
D.start();
D1.start();
for(int x = 0; x< 60;x++)
System.out.println(“Demo run” + x)
}
}
线程均有自己的默认名称.Thread-编号,该编号从零开始.
Thread.currdntThread():获取当前线程对象.
getName():获取线程名称.
设置线程名称:setName()或构造函数
例题:买票程序;
注意:假设5个窗口.
1.5个窗口必须同时运行.
2.不能卖重复的票
class Ticket extends Thread
{
private static int tick = 100;
public void run(){
While(true){
if(tick > 0){
System.out.println(Tread.currentThread().getName()+“..sale”+tick--);
}
}
}
}
class TicketDemo{
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();
}
}
若不用静态,如何解决.(用Runnable接口)
class Ticket implements Runnable
{
private int tick = 100;
public void run(){
While(true){
if(tick > 0){
System.out.println(Tread.currentThread().getName()+“..sale”+tick--);
}
}
}
}
class TicketDemo{
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);
Thread t5 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
Runnable接口是线程创建的第二种方式.
步骤:
1定义类实现Runnable接口.
2 覆盖Runnable接口中的run方法.
讲线程要运行的代码存放在该run方法中.
3通过Thread类建立线程对象.
4讲Runnable接口的子类对象作为实际参数传递给Thread类的构造函数.
为什么要将Runnable接口的子类对象传递给Thread的构造函数.
因为自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run方法.就必须明确该run方法所属对象.
5 调用Thread类的start地 方法开启线程并调用Runnable接口子类的run方法.
实现方式与继承方式有什么区别?
继承Thread:线程代码存放Thread子类run方法中.
实现Runnable:线程代码存在接口的子类的run方法中.
实现方式优势:避免了单继承的局限性.在定义线程时,建立使用实现方式.
多线程的安全问题.
class Ticket implements Runnable
{
private int tick = 100;
Object obj = new Object();
public void run(obj){
While(true){
if(tick > 0){
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Tread.currentThread().getName()+“..sale”+tick--);
}
}
}
}
class TicketDemo{
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);
Thread t5 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
发现代码打印出 0, -1 ,-2等错票.
原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行.导致共享数据错误.
解决办法:对多条操作共享数据的语句,只能让一个线程都执行完.在执行过程中,其他线程不能参与执行.
Java对于多线程的安全问题提供的解决办法是synchronized(同步代码块)
Synchronized(对象){
需要被同步的代码
}
class Ticket implements Runnable
{
private int tick = 100;
public void run(){
While(true){
Synchronized(对象){
if(tick > 0){
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Tread.currentThread().getName()+“..sale”+tick--);
}
}
}
}
}
class TicketDemo{
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);
Thread t5 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
同步时明确3点
1,明确哪些代码是多线程运行代码.
2,明确共享数据
3明确多线程运行代码中哪些语句是操作共享数据的.
同步的两种方式:同步代码块.同步函数(public synchronized void 函数名())
多线程同步代码的锁是this.
如果同步函数被静态修饰后,使用的是什么锁?
静态进内存后,内存中没有本类对象.但是一旦有该类对应到字节码文件对象.类名.class
该对象的类型是Class
静态的同步方法:使用的锁是该方法所在类的字节码文件对象.也就是类名.class
多线程---死锁
同步中嵌套同步
class Test{
Private boolean flag;
Tead(boolean flag){
this.flag = flag }
if (flag){
synchronized(MyLick.locka){
System.out.println(“if locka”)
synchronized(MyLick.lockb){
System.out.println(“if lockb”)
}
}
}
else{
synchronized(MyLick.lockb) {
System.out.println(“else lockb”)
synchronized(MyLick.locka){
System.out.println(“else locka”)
}
}
}
}
}
class MyLick {
static object locka = new object();
static object lockb = new object();
}
class DeadLockTest{
public static void main (String args[]){
Thread t1 = new Thread (new Test(true));
Thread t2 = new Thread (new Test(false));
t1.start();
T2.start();
}
}
- 黑马程序员_java 多线程(1)
- 黑马程序员_java多线程(1)
- 黑马程序员_java多线程
- 黑马程序员_JAVA多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_Java 多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_Java多线程
- 黑马程序员_Java多线程
- Windows核心编程——》第十九章 DLL的一些基本概念 (DLL Basics)
- 自定义进度条ProgressBar
- 算法中重要的问题类型
- 黑马程序员_java基础语句
- 类型转换运算-java
- 黑马程序员_java多线程(1)
- Spring的IOC原理
- 自己遇到问题清单
- 旋转卡壳 POJ 2079 Triangle
- 采集器延迟问题总结
- 排序之希尔排序
- 反射和代理机制
- 二叉树(按层遍历——队列模拟)
- 【二分查找】Search for a Range