Django进阶(三)

ORM

众所周知有很多不同的数据库系统,并且其中的大部分系统都包含Python接口,能够让我们更好的利用它们的功能,而这些系统唯一的缺点就是需要你了解SQL,如果你是一个更愿意操纵Python对象,而不是SQL查询的程序员,并且仍然希望使用关系数据库作为你的数据后端,那么我们可以使用ORM。

这些ORM系统的作者将纯SQL语句进行了抽象化处理,将其实现为Python中的对象,这样我们只操作对象就能完成与生成SQL语句相同的任务。就是用面向对象的方式去操作数据库的创建表以及增删改查等操作。

ORM优点:

1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

2 可以避免一些新手程序猿写sql语句带来的性能问题。

ORM缺点:

1  性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载登来减轻这个问题。效果很显著。

2  对于个别复杂查询,ORM仍然力不从心,为了解决这个问题,ORM一般也支持写raw sql。

3  通过QuerySet的query属性查询对应操作的sql语句

Model

下面要开始学习Django ORM语法了

单表的操作(增删改查)

--------------------增

from blog.models import *  # 首先导入应用里的models.py里的所有class(数据库里的各个表)

def base(request):
    # 增:
    # 方法一(推荐)
    # 固定结构: 类名(表名).objectes.create(**{"字段名1":"插入的字段内容","字段名2":"插入的字段内容"})
    Author.objects.create(**{"name": "liu"})

    # 方法二
    # 固定结构: 类名(表名).objectes.create(字段名1="插入的字段内容",字段名2="插入的字段内容")
    # 注意:字段名不加引号
    Author.objects.create(name="liu2")

    # 方法三
    author = Author(name="liu3")  # 实例化类(要操作的表)的对象并直接赋值
    author.save()  # 保存表的内容

    # 方法四
    author = Author()  # 实例化类(要操作的表)的对象
    author.name = "liu4"  # 逐个给对象的属性赋值
    author.save()  # 最后保存

--------------------查

# User2是blog.models中的一个类(表)

    # 方法一 filter
    # 固定结构: 类名(表名).objectes.filter(判断条件)
    user2_list = User2.objects.filter(name = "liu",sex="男")
    # filter括号内添加查询条件,多个条件用逗号隔开User2.objects.filter(name = "liu2",sex = "男")
    # 将所有满足条件的对象集合成QuerySet对象返回:<QuerySet [<User2: User2 object>, <User2: User2 object>]>
    # 即使只有一个对象满足条件也会返回QuerySet对象<QuerySet [<User2: User2 object>]>
    # 可以将QuerySet对象理解成一个list 可以通过索引获取单个对象:user2_list[0]
    # 当没有满足条件的对象则会返回一个空的QuerySet对象:<QuerySet []>
    # 获取到单个对象后可以通过 .字段名 获取该字段对应的内容 user2_list[0].name

    # 方法二 get
    # 固定结构: 类名(表名).objectes.get(判断条件)
    user2 = User2.objects.get(name = "liu2")
    # 只能获取到单个满足条件的对象,返回结果有且只有一个
    # 如果符合筛选条件的对象超过一个,或者没有都会抛出错误
    # 直接通过 .字段名 获取该字段对应的内容

    # 方法三 all
    # 固定结构: 类名(表名).objectes.all()
    user2_list = User2.objects.all()
    # 将该表(User2)的所有数据集合成queryset对象返回

    # 方法四 exclude
    # 固定结构: 类名(表名).objectes.exclude(判断条件)
    user2_list = User2.objects.exclude(name = "liu2")
    # 与filter正好相反,返回的结果是所有不满足括号内条件的对象的集合,返回的是QuerySet对象

    # -----------下面的方法都是对查询的结果进行处理再返回

    # values("字段名")
    User2.objects.filter(name = "liu2").values("sex")
    # QuerySet对象中只是想要获取某个字段,而不是全部的字段,将该字段放入 values("字段名")
    # 获取到QuerySet对象 列表包含字典的形式 < QuerySet[{‘sex‘: ‘男‘}, {‘sex‘: ‘男‘}]>

    # order_by("字段名")
    # 对查询结果按照 括号内的字段 从大到小排序,如果想要从小到大排序,则在引号内的字段名前添加一个减号
    User2.objects.filter(name="liu").order_by("-sex")

    # .reverse()
    User2.objects.filter(name="liu").reverse()
    # 对查询结果进行倒序,可以配合order_by使用

    # distinct()
    User2.objects.filter(name="liu").values("sex").distinct()
    # 剔除查询结果中完全相同的数据

    # count()
    User2.objects.filter(name="liu").count()
    # 返回查询结果(QuerySet)中包含的对象数量

    # first():  返回查询结果(QuerySet)中第一个对象

    # last():   返回查询结果(QuerySet)中最后一个对象

    # exists():  如果QuerySet包含数据,就返回True,否则返回False。

--------------------删

基于查的基础上进行删除,先查找到要删除的数据,然后进行删除

delete()
Author.objects.filter(name = "liu").delete()

删除一条数据,那么数据库中所有与该条数据相关的数据都会被删除,级联删除

--------------------改

基于查的基础上进行修改,先查找到要修改的数据,然后进行修改

    # update() 括号内添加要修改的字段及内容 sex = "aaa" 修改多个字段用逗号分隔开
    User2.objects.filter(name="liu2").update(sex = "女")

关联表操作

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名。

作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。

出版商模型:出版商有名称,地址,所在城市,省,国家和网站。

书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键。

书籍与作者:多对多关系,书籍与出版商:一对多关系,作者与出版商:无关系

创建表

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30, verbose_name="名称")
    address = models.CharField("地址", max_length=50)
    city = models.CharField(‘城市‘, max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    class Meta:
        verbose_name = ‘出版商‘
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name

class AuthorDetail(models.Model):
    sex = models.BooleanField(max_length=1, choices=((0, ‘男‘), (1, ‘女‘),))
    email = models.EmailField()
    address = models.CharField(max_length=50)
    birthday = models.DateField()
    author = models.OneToOneField(Author)
    # 一对一的关系 当表中存在两个相同的author时会报错

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField("Author")
    # 创建多对多关系的第三章表
    # models.ManyToManyField(Author) 括号里放入那个与该表有“多对多”关系的表名
    # 规定是一本书可以由多个作者共同完成,而一个作者又可以完成多本书,所以书与作者的关系是“多对多”
    # “多对多”的关系只有依靠第三章表才会完美体现两个表中的关系,而ManyToManyField(Author)会自动帮我们创建第三张表
    # 也可以在Author表里写 models.ManyToManyField(Book) 自动创建第三张表

    # 外键中加引号则 外键相关联的Publisher表不一定非要建在Book表之前,不加引号则必须建在该表之前
    # 是根据反射找到的Publisher表
    publishersss = models.ForeignKey("Publisher")
    # models.ForeignKey(Publisher) 括号里放入你想建立主外键的另一个数据表的表名(对应的主键的表的名称)
    # 规定是一本书只能由一家出版社出版,而一家出版社可以出版多本书,所以书与出版社之间的关系就是“多对一”的关系
    # 多对一的关系中应该在“多”的那个表里创建外键,所以这里添加外键
    # 我们写的字段是publisher 实际上django帮我们存入数据库中时自动存储成了publisher_id字段, 这是models.ForeignKey()的特殊性

    publication_date = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2, default=10)

    def __str__(self):
        return self.title

class User2(models.Model):
    name = models.CharField(max_length=30)
    sex = models.CharField(max_length=30)

 表中插入数据

from blog.models import * # 首先导入应用里的models.py里的所有class(数据库里的各个表)

# Author表
    Author.objects.create(**{
        "name":"zhangsan"
    })

    # AuthorDetail表
    # 字段:sex  email  address   birthday   author
    # 先获取外键author所要绑定的Author对象author3
    author3 = Author.objects.filter(name = "gaoer")[0]
    AuthorDetail.objects.create(**{
        "sex":True,
        "email":"[email protected]",
        "address":"中国北京",
        "birthday":"1991-10-24",
        "author":author3
        # 一对一关系中 author 赋值 Author对象author3
    })

    # Publisher表
    # 字段:name  address  city  state_province  country  website
    Publisher.objects.create(**{
        "name": "出版社002",
        "address": "地址002",
        "city": "城市002",
        "state_province": "省份002",
        "country": "国家002",
        "website": "网站002",
    })

    # Book表
    # 字段:title authors publisher publication_date price
    # 先获取要建立关系的Publisher对象
    publisher2 = Publisher.objects.filter(id = 3)[0]
    Book.objects.create(**{
        "title":"书籍005",
        "publishersss":publisher2,
        # 一对多关系中 直接在外键publishersss 赋值 publisher对象
        "publication_date":"2016-08-09",
        "price":50
    })
    #多对多 建立关系 先获取要绑定的Author对象
    authors8 =Author.objects.filter(id = 5)[0]
    #先获取要绑定的Book对象
    book001 = Book.objects.filter(title="书籍005")[0]
    # Book对象.关系字段.add(Author对象)
    book001.authors.add(authors8)
    # 由于我们是在Book表中与Author建立的ManyToManyField关系,所以是  Book对象.Book表中的关系字段名.add(Author对象)
    # 如果是在Author表中与Book建立的ManyToManyField关系,那么该是  Author对象.Author表中的关系字段名.add(Book对象)

--------------------关联表查询

   #----------------关联查找之“一对多”的关系
    # 双下划线可以理解为只是一个判断条件,任何有关联的表都可以查到
    # 固定写法:外键名__外键关联表的字段名
    # Book.objects.filter(publishersss__name="出版社001")[0]
    # Publisher.objects.filter(book__title="书籍001")

    # 都是已知A表中的数据,查找与他相关的B表中的数据

    # 当A表中的某行数据只能绑定B表中的一行数据时(一个Book只能对应一个Publisher)
    # 直接 .外键名称
    # book = Book.objects.filter(id = 1)[0]
    # publisher = book.publishersss
    # 由于是“一对多”的关系 所以publisher是一个对象 而不是QuerySet对象

    # 当A表中的某行数据可以绑定多个B表中的数据(一个Publisher对应多个Book)
    # 需要用到 表名_set  固定写法:表名_set
    # publisher =Publisher.objects.filter(id=1)[0]
    # book=publisher.book_set.all() #  获取到QuerySit对象集合
    # .book_set 跳转到与Publisher对象关联的book表
    #  Publisher.objects.filter(id=1)[0].book_set   相当于  Book.objects 只不过都是与id=1的publisher绑定的书的对象
    #  之后可以根据查询语法查询了 .filter .all .get

    # ----------------关联查找之“多对多”的关系

    # 根据书的ID找到对应的作者 是个QuerySet对象,拿到第一个作者的作者信息.authordetail
    # author = Author.objects.filter(book__id=1)[0].authordetail

    # -----QuerySet对象.values("相关联的表外键字段名__相关联的表的字段名")
    # 取到与之相关联对象的字段,不加“__字段名” 默认取到与之相关联对象的主键
    # Book.objects.filter(title=‘书籍001‘).values(‘publishersss__city‘)[0]
    # -----QuerySet对象.values("表名__外键字段名")
    # A表和B表有关联,B表和C表有关联,A和C无关联,已知A,查到与A有关联的B再查到与B有关联的C
    # A对象点.values(‘共同关联B表名__B中关联C的外键字段名‘)  得到C表主键
    # Author.objects.filter(id=1).values(‘book__publishersss‘)

--------------------聚合查询:

通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。

首先导入模块 from django.db.models import aggregates, Avg, Sum, Max, Min

# 从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有图书的集合。
    # 得到字典形式结果
    # 默认:
    a = Book.objects.all().aggregate(Avg("price"))
    print(a)  # 执行结果{‘price__avg‘: 60.0}
    # aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值
    # aggregate()是QuerySet的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。   # 键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它:
    a = Book.objects.all().aggregate(pingjunjiage=Avg("price"))
    print(a)  # 执行结果{‘pingjunjiage‘: 60.0}
    # 如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
    a = Book.objects.aggregate(Avg(‘price‘), Max(‘price‘), Min(‘price‘), Sum("price"))
    print(a)
    # 执行结果{‘price__max‘: Decimal(‘80.00‘), ‘price__avg‘: 60.0, ‘price__sum‘: Decimal(‘240.00‘), ‘price__min‘: Decimal(‘50.00‘)}
    

--------------------分组查询:

可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。

 查询alex出的书总价格                   

查询各个作者出的书的总价格,这里就涉及到分组了,分组条件是authors__name

查询各个出版社最便宜的书价是多少

--------------------F查询和Q查询



    仅仅靠单一的关键字参数查询已经很难满足查询要求。此时Django为我们提供了F和Q查询:

    # F 使用查询条件的值,专门取对象中某列值的操作

    # from django.db.models import F
    # models.Tb1.objects.update(num=F(‘num‘)+1)

    # Q 构建搜索条件
    from django.db.models import Q

    # 1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
    q1 = models.Book.objects.filter(Q(title__startswith=‘P‘)).all()
    print(q1)  # [<Book: Python>, <Book: Perl>]

    # 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
    Q(title__startswith=‘P‘) | Q(title__startswith=‘J‘)

    # 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
    Q(title__startswith=‘P‘) | ~Q(pub_date__year=2005)

    # 4、应用范围:

    # Each lookup function that takes keyword-arguments (e.g. filter(),
    #  exclude(), get()) can also be passed one or more Q objects as
    # positional (not-named) arguments. If you provide multiple Q object
    # arguments to a lookup function, the arguments will be “AND”ed
    # together. For example:

    Book.objects.get(
        Q(title__startswith=‘P‘),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )

    # sql:
    # SELECT * from polls WHERE question LIKE ‘P%‘
    #     AND (pub_date = ‘2005-05-02‘ OR pub_date = ‘2005-05-06‘)

    # import datetime
    # e=datetime.date(2005,5,6)  #2005-05-06

    # 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
    # 正确:
    Book.objects.get(
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
        title__startswith=‘P‘)
    # 错误:
    Book.objects.get(
        question__startswith=‘P‘,
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

QuerySet

QuerySet对象特点:

1. 可迭代的

2.可切片

#objs=models.Book.objects.all()#[obj1,obj2,ob3...]

    #QuerySet:   可迭代

    # for obj in objs:#每一obj就是一个行对象
    #     print("obj:",obj)
    # QuerySet:  可切片

    # print(objs[1])
    # print(objs[1:4])
    # print(objs[::-1])

QuerySet对象的高效使用:

<1>Django的queryset是惰性的

     Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
     到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
     上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
     这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。

<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
   为了验证这些,需要在settings里加入 LOGGING(验证方式)
        obj=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)

        # if obj:
        #     print("ok")

<3>queryset是具有cache的
     当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
    (evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
     你不需要重复运行通用的查询。
        obj=models.Book.objects.filter(id=3)

        # for i in obj:
        #     print(i)
                          ## models.Book.objects.filter(id=3).update(title="GO")
                          ## obj_new=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)   #LOGGING只会打印一次

<4>
     简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
     数据!为了避免这个,可以用exists()方法来检查是否有数据:

            obj = Book.objects.filter(id=4)
            #  exists()的检查可以避免数据放入queryset的cache。
            if obj.exists():
                print("hello world!")

<5>当queryset非常巨大时,cache会成为问题

     处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
     进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
     来获取数据,处理完数据就将其丢弃。
        objs = Book.objects.all().iterator()
        # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
        for obj in objs:
            print(obj.name)
        #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
        for obj in objs:
            print(obj.name)

     #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
     #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询

总结:
    queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
会造成额外的数据库查询。
时间: 2024-12-12 11:44:11

Django进阶(三)的相关文章

Django进阶三

一.Django Admin的简单用法 创建管理员账号 python manage.py createsuperuser 在admin注册我们的表(/project/app01/admin.py) from app01 import models admin.site.register(models.类名) 示例: from django.contrib import admin from app01 import models # Register your models here admin

Python进阶(三十六)-Web框架Django项目搭建全过程

Python进阶(三十六)-Web框架Django项目搭建全过程 ??IDE说明: Win7系统 Python:3.5 Django:1.10 Pymysql:0.7.10 Mysql:5.5 ??Django 是由 Python 开发的一个免费的开源网站框架,可以用于快速搭建高性能,优雅的网站! Django 特点 强大的数据库功能 用python的类继承,几行代码就可以拥有一个丰富,动态的数据库操作接口(API),如果需要你也能执行SQL语句. 自带的强大的后台功能 几行简单的代码就让你的网

python 全栈 web框架 Django进阶

django 进阶 基础中,一些操作都是手动创建连接的非主流操作,这样显得太low,当然也是为了熟悉这个框架! 实际中,django自带连接数据库和创建app的机制,同时还有更完善的路由系统机制.既然基础已经了解,那就聊聊主流的东西. 一.web框架重新认知: 既然都是框架,那肯定是都包含了这些模块和对应的功能!但是不同框架之间也是有些诧异,毕竟封装的方法不同. Django: - 路由(url路由系统) - 视图(视图函数) - 模板(模版页面) - 数据库 ---> ORM(类-表:对象-行

django进阶-3

先看效果图: 登陆admin后的界面: 查看作者: 当然你也可以定制admin, 使界面更牛逼 数据库表结构: app01/models.py 1 from django.db import models 2 from django.utils.html import format_html #把字符串变成html 3 4 # Create your models here. 5 class Author(models.Model): 6 first_name = models.CharFiel

【Python全栈-后端开发】Django进阶2-Form表单

Django进阶2-Form表单 Django的Form主要具有一下几大功能: 生成HTML标签(可以保留上次输入内容) 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 一.小试牛刀 1.创建Form类 在app01 文件夹下-->创建新的.py 文件 from django.forms import Form from django.forms import widgets from django.forms import fields class M

Java进阶(三十四)Integer与int的种种比较你知道多少?

Java进阶(三十四)Integer与int的种种比较你知道多少? 前言 如果面试官问Integer与int的区别:估计大多数人只会说到两点:Ingeter是int的包装类,注意是一个类:int的初值为0,Ingeter的初值为null.但是如果面试官再问一下Integer i = 1;int ii = 1; i==ii为true还是为false?估计就有一部分人答不出来了,如果再问一下其他的,估计更多的人会头脑一片混乱.所以我对它们进行了总结,希望对大家有帮助. 首先看代码: package

Python爬虫进阶三之Scrapy框架安装配置

初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此整理如下. Windows 平台: 我的系统是 Win7,首先,你要有Python,我用的是2.7.7版本,Python3相仿,只是一些源文件不同. 官网文档:http://doc.scrapy.org/en/latest/intro/install.html,最权威哒,下面是我的亲身体验过程. 1.安装Python 安装过程我就不多说啦,我的电

3. 蛤蟆的数据结构进阶三静态查询之折半查询

3. 蛤蟆的数据结构进阶三静态查询之折半查询 本篇名言:"但是话不行,要紧的是做. --鲁迅" 继续来看静态查询的折半查询. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47211637 1.  折半查找 折半查找要求查找表用顺序存储结构存放且各数据元素按关键字有序(升序或隆序)排列,也就是说折半查找只适用于对有序顺序表进行查找. 折半查找的基本思想是:首先以整个查找表作为查找范围,用查找条件中给定值k与中间位置

Python进阶(三十五)-Fiddler命令行和HTTP断点调试

Python进阶(三十五)-Fiddler命令行和HTTP断点调试 一. Fiddler内置命令 ??上一节(使用Fiddler进行抓包分析)中,介绍到,在web session(与我们通常所说的session不是同一个概念,这里的每条HTTP请求都称为一个session).界面中能够看到Fiddler抓取的全部HTTP请求.而为了更加方便的管理全部的session, Fiddler提供了一系列内置的函数用于筛选和操作这些session(习惯命令行操作Linux的童鞋应该能够感受到这会有多么方便

Python进阶(三十四)-Python3多线程解读

Python进阶(三十四)-Python3多线程解读 线程讲解 ??多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度. 程序的运行速度可能加快. 在一些等待的任务实现上如用户输入.文件读写和网络收发数据等,线程就比较有用了.在这种情况下我们可以释放一些珍贵的资源如内存占用等等. ??线程在执行过程中与进程还是有区别的.每个独立