为了账号安全,请及时绑定邮箱和手机立即绑定

多线程

标签:
Java

1.如何解决多线程的安全问题?
校验一个多线程程序是否有安全问题的隐患的前提条件:
1)当前程序是否是多线程环境
2)是否有共享数据
3)是否有多条语句对共享数据进行操作

  1. 锁对象格式:
    synchronized(锁对象){
    针对多条语句对共享数据操作代码;
    }

    锁对象:一定要同一个锁(每个线程只能使用同一把锁)    售票问题    package org.westos_05;

public class SellTicket implements Runnable {

//定义100张票private int tickets = 100 ;private Object obj = new Object() ;private Demo d = new Demo() ;@Overridepublic void run() {    while(true) {        //t1,t2,t3        synchronized(d) { //门的开和关            //t1进来,门会关掉            //t2进来,门关掉            //t3进来,门关掉            if(tickets>0) {                try {                    //0.1                    Thread.sleep(100);                 } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println(Thread.currentThread().getName()                        +"正在出售第"+(tickets--)+"张票");                //窗口1正在出售第100张票                //窗口2正在出售第99张票                //窗口3正在出售98张票                //....                //虽然加入延迟操作,就是synchronized,不会存在0或者负票了            }        }    }}

}

public class SellTicketDemo {

public static void main(String[] args) {    //创建资源类对象(共享资源类/目标对象)    SellTicket st = new SellTicket() ;    //创建线程类对象    Thread t1 = new Thread(st, "窗口1") ;    Thread t2 = new Thread(st ,"窗口2") ;    Thread t3 = new Thread(st, "窗口3") ;    //启动线程    t1.start();    t2.start();    t3.start();}

}

还可以将锁对象进行包装,如果包装成静态类,锁对象为类名.class;
如果是非静态类,锁对象为this ;

  1. //线程安全的类StringBuffer sb = new StringBuffer() ;Vector<String> v = new Vector<String>() ;Hashtable<String, String> hm = new Hashtable<String,String>() ;//Vector<String>它线程安全的类,还是不习惯使用这个集合,通过ArrayList集合:线程不安全的类List<String> array = new ArrayList(); //线程不安全的类//public static <T> List<T> synchronizedList(List<T> list)//返回指定列表支持的同步(线程安全的)列表List list = Collections.synchronizedList(array) ; //线程安全的方法

    Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构

    可以使用Lock锁进行具体的锁定操作类   提供了具体的实现类:ReentrantLock
    加锁并且去释放锁

        package org.westos_07;
    1. // Jdk5.0以后,java提供了一个具体的锁: 接口:Lock
      private Lock lock= new ReentrantLock(); //显示获取锁的前提,一定要创建Lock接口对象

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicket implements Runnable {

// 定义票private int tickets = 100;// Object obj = new Object();// Jdk5.0以后,java提供了一个具体的锁: 接口:Lockprivate Lock lock= new ReentrantLock(); //显示获取锁的前提,一定要创建Lock接口对象@Overridepublic void run() {    while (true) {        try { //try...finally            lock.lock(); // 获取锁    syncrhonized(obj)            if (tickets > 0) {                try {                    Thread.sleep(100);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");            }        } finally {//释放锁            if(lock!=null) {                lock.unlock();            }        }    }}

}

public class SellTicketDemo {

public static void main(String[] args) {    SellTicket st = new SellTicket() ;    Thread t1 = new Thread(st,"窗口1") ;    Thread t2 = new Thread(st,"窗口2") ;    Thread t3 = new Thread(st,"窗口3") ;    //启动线程    t1.start();     t2.start();     t3.start();}

}

5.消费者生产者问题解密死锁;

package org.westos_11;

public class Student {

String name ;int age ;boolean flag; //默认没有数据,如果是true,说明有数据

}

package org.westos_11;

//消费者线程
public class GetThread implements  Runnable {
private Student s ;

    public GetThread(Student s) {        this.s = s ;    }@Overridepublic void run() {    //输出该学生数据

//      Student s = new Student() ;
while(true) {
synchronized (s) {
//如果本身消费者有数据
if(!s.flag) {
try {
s.wait();//和网络编程中TCP编程里面的accept() 都属于阻塞式方法
//消费线程等待,等待该线程先输出这些数据(立即释放锁对象)

                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            System.out.println(s.name +"----"+s.age);//高圆圆---27            //如果没有数据类,            s.flag = false ;            //通知t1线程,赶紧产生数据            s.notify(); //唤醒单个线程        }        //张杨---27    }}

}

public SetThread(Student s) {    this.s = s ;}//定义一个变量private int x = 0 ;@Overridepublic void run() {    //设置学生数据

//      Student s = new Student() ;
while(true) {
synchronized (s) {
//判断有没有数据的情况
if(s.flag) {

                try {                    s.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            if(x%2 ==0) {                s.name = "高圆圆" ;    //高圆圆---27                s.age = 27 ;            }else {                s.name = "张杨";                //张杨                s.age = 28 ;            }            x++ ;            //如果有数据了,更改flag值            s.flag = true ;//有数据了            //通知t2线程消费数据,唤醒            s.notify();  //唤醒t2线程,唤醒之后t1,t2都互相抢占        }    }}

}

public class StudentDemo {

public static void main(String[] args) {    //针对同一个对象进行操作    Student s = new Student() ;    //创建线程类对象    SetThread st = new SetThread(s) ;    GetThread gt = new GetThread(s) ;    //创建线程了对象    Thread t1 = new Thread(st) ; //生产者    Thread t2 = new Thread(gt) ;//消费者    //启动线程    t1.start();    t2.start();}

}public class StudentDemo {

public static void main(String[] args) {    //针对同一个对象进行操作    Student s = new Student() ;    //创建线程类对象    SetThread st = new SetThread(s) ;    GetThread gt = new GetThread(s) ;    //创建线程了对象    Thread t1 = new Thread(st) ; //生产者    Thread t2 = new Thread(gt) ;//消费者    //启动线程    t1.start();    t2.start();}

}

  1. 线程池问题

package org.westos_13;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

线程池:多个线程执行完毕,它会重新回到线程池中,等待被利用,不会变成垃圾!
和线程池有关的类
类 Executors: 一种工厂类

    方法:        和线程池的创建有关系        public static ExecutorService newFixedThreadPool(int nThreads)        创建一个可重用固定线程数的线程池

ExecutorService:可以执行异步任务
创建一个线程池,执行接口中的方法
提交:Future<?> submit(Runnable task)
<T> Future<T> submit(Callable<T> task)提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future
Future:接口
Future 表示异步计算的结果

        线程池调用完毕可以关闭的            void shutdown():关闭之前,会提交刚才的任务

public class ExceutorsDemo {

public static void main(String[] args) {    //创建一个线程池    ExecutorService pool = Executors.newFixedThreadPool(2) ;//创建一个线程池中包含了2条线程    //提交和Runnable接口的方法或者Callable(提交任务)    pool.submit( new MyRunnable()) ;    pool.submit( new MyRunnable()) ;    //pool-1-thread-2 :线程池-池数-线程类对象的描述-编号(从1开始)    //关闭线程池    pool.shutdown();}

}

package org.westos_13;

public class MyRunnable implements Runnable {

@Overridepublic void run() {    for(int x = 0 ; x < 100 ; x ++) {        System.out.println(Thread.currentThread().getName()+":"+x);    }}

}

  1. 简单工厂模式--->静态工厂方法模式

    设计一个工厂类:
    工厂类提供一些静态方法,间接的去创建具体的对象

    优点:
    不需要在创建具体类的对象,而是把创建的工作交给了工厂类来创建!
    弊端:如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护

  2. 工厂方法模式
    提供一个抽象类(抽象工厂)还需要提供一个接口(工厂接口),每一个具体的类都有对应的工厂类(实现工厂接口)
    具体对象的创建工作由继承抽象工厂的具体类实现

    优点:
    客户端不需要在负责对象的创建(不需显示创建具体对象),从而明确了各个类的职责,
    如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强      了系统的扩展性
    弊端:
    书写代码量大了!

  3. 设计模式之单例模式
    单例模式核心思想:某些类的对象在创建的时候 ,在系统内存始终只有一个对象!
    单例模式分类:
    1)饿汉式 2)懒汉式(类似于多线程环境..) 两种分类在设计上几乎一样

  4. 饿汉式:
    在加载那个类的时候,对象的创建工作就已经完成了!

    1)定义个类,将该类的无参构造方法私有化2)在该类的成员位置创建该类对象 并且一定要私有化,防止外界更改这个对象3)在该类中提供静态成员方法(返回值就是创建的那个对象),能被当前类直接调用,static修饰
  5. 懒汉式:
    符合单例模式核心思想
    1)自定义一个类,将无参构造私有化
    2)在成员位置声明变量
    3)提供公共静态功能,在里面判断的创建该类对象,返回该类对象

    如果是开发中,那么就使用饿汉式(饿汉式它不会出现问题的单例模式)
    如果是面试中,那么使用懒汉式(因为他是可能出现问题的一种单例模式)

    1. 面试题:
      你使用过单例模式吗?简单介绍一种单例模式,请用代码设计
      面试官想问的是:使用设计单例的懒汉式,能否想到使用同步机制解决线程的安全问题..

      懒汉式(延迟加载 -->懒加载)
      可能会出现问题
      --->    多线程的问题
      --->校验多线程安全问题的标准
      1)是否是多线程环境
      2)是否有共享数据
      3)是否有多条语句对共享数据进行操作  (使用同步机制进行操作)

13.网络的概念
计算机网络:
多台计算机通过网络协议,实现网络资源共享和信息传递!

http://localhost:端口号 (80)www.baidu.com

username:admin
password:%AE%.... MD5算法   加密很难解密

网络通信三要素

1)ip地址2)端口号3)应该有一些规则(协议UDP/TCP)举例:    我想和高圆圆聊天...    1)找到她,才能和她说话------>IP地址    2)假设找她了,怎么说呢?        对着她耳朵说话------->port端口号    3)要对她:i love you             假设不懂英文,----->定义规则(协议)

IP地址:
192.168.10.1        (通过8421码将可以由0,1组成的一些数据)
点分十进制法:十进制.十进制.十进制.十进制  书写简单

    11000000.0000100....    Ip地址的分类:        IP地址的组成        IP地址 = 网络号码+主机地址        A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码                一般情况:国防部/大的国部门        B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码                    一般情况:大学里面的多媒体教室        C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码                    私人地址

A类  1.0.0.1---127.255.255.254   (1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)                           (2)127.X.X.X是保留地址,用做循环测试用的。
B类  128.0.0.1---191.255.255.254 172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
C类  192.0.0.1---223.255.255.254 192.168.X.X是私有地址
D类  224.0.0.1---239.255.255.254    
E类  240.0.0.1---247.255.255.254

127.0.0.1--->表示本地计算机的回环地址
dos
ipconfig
ping ip地址   是否能通信

        声呐系统(二战)

端口号:0~65535有效端口号
0-1024属于保留端口

mysql:3306

协议:
UDP协议   --->UDP编程
不需要建立连接通道的
数据大小有限制
不可靠连接
执行效率高
TCP协议   ---->TCP编程
需要建立连接通道
数据大小无限制
可靠连接
执行效率低

打电话:看成TCP协议  建立连接通道发短信:UDP协议   不需要建立连接通道
  1. .InetAddress:类表示互联网协议 (IP) 地址

    如果一个类中没有构造方法,没有字段,只有成员方法?有什么特征
    1)应该有一些静态功能(Math类,Arrays,Collections...)
    2)可能符合一种单例模式(饿汉/懒汉)
    3)该类中的某些静态成员方法的返回值是该类本身

    举例
    public class Demo{

            public static Demo getDemo(){                new Demo() ;        }}

    常用方法:
    public static InetAddress getByName(String host)
    throws UnknownHostException在给定主机名的情况下确定主机的 IP 地址。
    参数:
    主机名可以是机器名(如 "java.sun.com"),也可以是其 IP 地址的文本表示形式;

  2. Udp编程

    1)不需要建立连接通道
    2)数据大小有限制
    3)不可靠连接---->传输速度快!

    发送端的开发步骤:
    1)创建发送端的Socket对象
    2)创建数据,并打包
    3)调用当前发送端Socket对象中的发送的方法
    4)关闭资源

    方法:  buf - 包数据。
    offset - 包数据偏移量。
    length - 包数据长度。
    address - 目的地址。
    port - 目的端口号。

    Udp编程的接收端 开发步骤:
    1)创建Socket对象
    2)创建一个数据报包(接收容器)
    3)调用Socket对象中的接收的方法
    4)解析实际传递的数据
    5)将解析的数据(ip,数据)展示在控制台上
    6)关闭资源
    注意:
    接收端不要运行多次,会出现异常:
    java.net.BindException: Address already in use: Cannot bind

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消